mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
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>
This commit is contained in:
parent
907d733ffe
commit
2155748c41
@ -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,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,
|
||||
|
Loading…
Reference in New Issue
Block a user