Signed-off-by: Conor McCarthy <cmccarthy(a)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 = ¤t->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