Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ValveSoftware/vkd3d.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConor McCarthy <cmccarthy@codeweavers.com>2019-10-24 15:20:49 +0300
committerAlexandre Julliard <julliard@winehq.org>2019-10-27 21:14:38 +0300
commit2155748c418e862a906c8c43ead382f30dd40de1 (patch)
tree2a75cf15afb92669b6143e5906202270b81d33c1
parent907d733ffe18635e17338a89edbc3b4947188de6 (diff)
vkd3d: Add support for multiplanar depth/stencil state transitions.
If separate transitions of the depth and stencil plane occur in the same array of barriers, they will be consolidated into one Vulkan layout transition. This can only be supported for combinations of depth read and depth write states, or identical states. Signed-off-by: Conor McCarthy <cmccarthy@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
-rw-r--r--libs/vkd3d/command.c118
1 files changed, 106 insertions, 12 deletions
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 59ea4829..4338cd4e 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,55 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
continue;
}
+ if (multiplanar_handled && multiplanar_handled[i])
+ 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(*multiplanar_handled)))))
+ {
+ 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 +3887,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 +3986,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 +4831,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 +4864,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,