[PATCH] vkd3d: Add support for multiplanar depth/stencil state transitions.

Conor McCarthy cmccarthy at codeweavers.com
Tue Oct 22 08:02:37 CDT 2019


Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d/command.c | 121 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 109 insertions(+), 12 deletions(-)

diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 59ea482..5f7fb21 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -1872,7 +1872,7 @@ static void d3d12_command_list_invalidate_bindings(struct d3d12_command_list *li
     }
 }
 
-static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
+static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, unsigned int stencil_state,
         const struct d3d12_resource *resource, VkQueueFlags vk_queue_flags, const struct vkd3d_vulkan_info *vk_info,
         VkAccessFlags *access_mask, VkPipelineStageFlags *stage_flags, VkImageLayout *image_layout)
 {
@@ -1911,7 +1911,7 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
                 }
                 else if (resource->present_state != D3D12_RESOURCE_STATE_COMMON)
                 {
-                    vk_barrier_parameters_from_d3d12_resource_state(resource->present_state,
+                    vk_barrier_parameters_from_d3d12_resource_state(resource->present_state, 0,
                             resource, vk_queue_flags, vk_info, access_mask, stage_flags, image_layout);
                     return true;
                 }
@@ -1945,7 +1945,12 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
             *stage_flags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
                     | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
             if (image_layout)
-                *image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+            {
+                if (!stencil_state || (stencil_state & D3D12_RESOURCE_STATE_DEPTH_WRITE))
+                    *image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+                else
+                    *image_layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
+            }
             return true;
 
         case D3D12_RESOURCE_STATE_COPY_DEST:
@@ -1975,7 +1980,17 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
             *access_mask = 0;
             *stage_flags = 0;
             if (image_layout)
-                *image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
+            {
+                if (stencil_state & D3D12_RESOURCE_STATE_DEPTH_WRITE)
+                {
+                    *image_layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
+                    *access_mask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+                }
+                else
+                {
+                    *image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
+                }
+            }
             break;
 
         case D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE:
@@ -2096,7 +2111,7 @@ static void d3d12_command_list_transition_resource_to_initial_state(struct d3d12
     barrier.oldLayout = d3d12_resource_is_cpu_accessible(resource) ?
             VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED;
 
-    if (!vk_barrier_parameters_from_d3d12_resource_state(resource->initial_state,
+    if (!vk_barrier_parameters_from_d3d12_resource_state(resource->initial_state, 0,
             resource, list->vk_queue_flags, vk_info, &barrier.dstAccessMask, &dst_stage_mask, &barrier.newLayout))
     {
         FIXME("Unhandled state %#x.\n", resource->initial_state);
@@ -3710,6 +3725,44 @@ static void STDMETHODCALLTYPE d3d12_command_list_SetPipelineState(ID3D12Graphics
     list->state = state;
 }
 
+static bool is_ds_multiplanar_resolvable(unsigned int first_state, unsigned int second_state)
+{
+    /* Only combinations of depth/stencil read/write are supported. */
+    return first_state == second_state
+            || ((first_state & (D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_DEPTH_WRITE))
+            && (second_state & (D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_DEPTH_WRITE)));
+}
+
+static unsigned int d3d12_find_ds_multiplanar_transition(const D3D12_RESOURCE_BARRIER *barriers,
+        unsigned int i, unsigned int barrier_count, unsigned int sub_resource_count)
+{
+    unsigned int sub_resource_idx = barriers[i].u.Transition.Subresource;
+    unsigned int j;
+
+    for (j = i + 1; j < barrier_count; ++j)
+    {
+        if (barriers[j].Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION
+                && barriers[j].u.Transition.pResource == barriers[i].u.Transition.pResource
+                && sub_resource_idx % sub_resource_count == barriers[j].u.Transition.Subresource % sub_resource_count)
+        {
+            /* Second barrier must be for a different plane. */
+            if (barriers[j].u.Transition.Subresource == sub_resource_idx)
+                return 0;
+
+            /* Validate the second barrier and check if the combination of two states is supported. */
+            if (!is_valid_resource_state(barriers[j].u.Transition.StateBefore)
+                    || !is_ds_multiplanar_resolvable(barriers[i].u.Transition.StateBefore, barriers[j].u.Transition.StateBefore)
+                    || !is_valid_resource_state(barriers[j].u.Transition.StateAfter)
+                    || !is_ds_multiplanar_resolvable(barriers[i].u.Transition.StateAfter, barriers[j].u.Transition.StateAfter)
+                    || barriers[j].u.Transition.Subresource >= sub_resource_count * 2u)
+                return 0;
+
+            return j;
+        }
+    }
+    return 0;
+}
+
 static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsCommandList1 *iface,
         UINT barrier_count, const D3D12_RESOURCE_BARRIER *barriers)
 {
@@ -3717,6 +3770,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
     bool have_aliasing_barriers = false, have_split_barriers = false;
     const struct vkd3d_vk_device_procs *vk_procs;
     const struct vkd3d_vulkan_info *vk_info;
+    bool *multiplanar_handled = NULL;
     unsigned int i;
 
     TRACE("iface %p, barrier_count %u, barriers %p.\n", iface, barrier_count, barriers);
@@ -3746,6 +3800,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
         {
             case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:
             {
+                unsigned int state_before, state_after, stencil_state_before = 0, stencil_state_after = 0;
                 const D3D12_RESOURCE_TRANSITION_BARRIER *transition = &current->u.Transition;
 
                 if (!is_valid_resource_state(transition->StateBefore))
@@ -3767,18 +3822,58 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
                     continue;
                 }
 
+                if (multiplanar_handled && multiplanar_handled[i])
+                {
+                    FIXME("Skipping resource %p\n", resource);
+                    continue;
+                }
+
+                state_before = transition->StateBefore;
+                state_after = transition->StateAfter;
+
                 sub_resource_idx = transition->Subresource;
 
-                if (!vk_barrier_parameters_from_d3d12_resource_state(transition->StateBefore,
+                if (sub_resource_idx != D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES
+                        && (resource->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
+                {
+                    unsigned int sub_resource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
+                    unsigned int j = d3d12_find_ds_multiplanar_transition(barriers, i, barrier_count, sub_resource_count);
+                    if (j && (multiplanar_handled || (multiplanar_handled = vkd3d_calloc(barrier_count, sizeof(bool)))))
+                    {
+                        multiplanar_handled[j] = true;
+                        if (sub_resource_idx >= sub_resource_count)
+                        {
+                            sub_resource_idx -= sub_resource_count;
+                            /* The stencil barrier is at i, depth at j. */
+                            state_before = barriers[j].u.Transition.StateBefore;
+                            state_after = barriers[j].u.Transition.StateAfter;
+                            stencil_state_before = transition->StateBefore;
+                            stencil_state_after = transition->StateAfter;
+                        }
+                        else
+                        {
+                            /* Depth at i, stencil at j. */
+                            stencil_state_before = barriers[j].u.Transition.StateBefore;
+                            stencil_state_after = barriers[j].u.Transition.StateAfter;
+                        }
+                    }
+                    else if (sub_resource_idx >= sub_resource_count)
+                    {
+                        FIXME_ONCE("Unhandled sub-resource idx %u.\n", sub_resource_idx);
+                        continue;
+                    }
+                }
+
+                if (!vk_barrier_parameters_from_d3d12_resource_state(state_before, stencil_state_before,
                         resource, list->vk_queue_flags, vk_info, &src_access_mask, &src_stage_mask, &layout_before))
                 {
-                    FIXME("Unhandled state %#x.\n", transition->StateBefore);
+                    FIXME("Unhandled state %#x.\n", state_before);
                     continue;
                 }
-                if (!vk_barrier_parameters_from_d3d12_resource_state(transition->StateAfter,
+                if (!vk_barrier_parameters_from_d3d12_resource_state(state_after, stencil_state_after,
                         resource, list->vk_queue_flags, vk_info, &dst_access_mask, &dst_stage_mask, &layout_after))
                 {
-                    FIXME("Unhandled state %#x.\n", transition->StateAfter);
+                    FIXME("Unhandled state %#x.\n", state_after);
                     continue;
                 }
 
@@ -3795,7 +3890,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
                 VkAccessFlags access_mask;
 
                 resource = unsafe_impl_from_ID3D12Resource(uav->pResource);
-                vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+                vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0,
                         resource, list->vk_queue_flags, vk_info, &access_mask, &stage_mask, &image_layout);
                 src_access_mask = dst_access_mask = access_mask;
                 src_stage_mask = dst_stage_mask = stage_mask;
@@ -3894,6 +3989,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
         }
     }
 
+    vkd3d_free(multiplanar_handled);
+
     if (have_aliasing_barriers)
         FIXME_ONCE("Aliasing barriers not implemented yet.\n");
 
@@ -4737,7 +4834,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID
         buffer_barrier.offset = cpu_descriptor->uav.buffer.offset;
         buffer_barrier.size = cpu_descriptor->uav.buffer.size;
 
-        vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+        vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0,
                 resource_impl, list->vk_queue_flags, vk_info, &buffer_barrier.dstAccessMask, &stage_mask, NULL);
 
         VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
@@ -4770,7 +4867,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID
         image_barrier.image = resource_impl->u.vk_image;
         image_barrier.subresourceRange = range;
 
-        vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+        vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0,
                 resource_impl, list->vk_queue_flags, vk_info, &image_barrier.dstAccessMask, &stage_mask, NULL);
 
         VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
-- 
2.23.0




More information about the wine-devel mailing list