Signed-off-by: Conor McCarthy cmccarthy@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,