From 53e83b7031be488e4d120b1d56456ade509e84d3 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 4 Apr 2022 13:55:00 +0200 Subject: dzn: Support independent depth/stencil access Needed for VK_KHR_maintenance2. While at it, fix various places where we were only issuing resource state transition on the first sub-resource instead of doing it per-layer/aspect. Reviewed-by: Erik Faye-Lund Part-of: --- src/microsoft/vulkan/dzn_cmd_buffer.cpp | 184 ++++++++++++++++++++------------ src/microsoft/vulkan/dzn_image.cpp | 12 ++- src/microsoft/vulkan/dzn_pass.cpp | 82 ++++++++++++-- src/microsoft/vulkan/dzn_private.h | 10 +- 4 files changed, 211 insertions(+), 77 deletions(-) diff --git a/src/microsoft/vulkan/dzn_cmd_buffer.cpp b/src/microsoft/vulkan/dzn_cmd_buffer.cpp index 3c3a9fe6c39..155d705ecbf 100644 --- a/src/microsoft/vulkan/dzn_cmd_buffer.cpp +++ b/src/microsoft/vulkan/dzn_cmd_buffer.cpp @@ -720,30 +720,32 @@ dzn_CmdPipelineBarrier2(VkCommandBuffer commandBuffer, cmdbuf->cmdlist->ResourceBarrier(1, &aliasing_barrier); - D3D12_RESOURCE_BARRIER transition_barrier = { - .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, - .Transition = { - .pResource = image->res, - .StateAfter = dzn_image_layout_to_state(ibarrier->newLayout), - }, - }; + dzn_foreach_aspect(aspect, range->aspectMask) { + D3D12_RESOURCE_BARRIER transition_barrier = { + .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, + .Transition = { + .pResource = image->res, + .StateAfter = dzn_image_layout_to_state(ibarrier->newLayout, aspect), + }, + }; - if (ibarrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED || - ibarrier->oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) - transition_barrier.Transition.StateBefore = image->mem->initial_state; - else - transition_barrier.Transition.StateBefore = dzn_image_layout_to_state(ibarrier->oldLayout); + if (ibarrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED || + ibarrier->oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { + transition_barrier.Transition.StateBefore = image->mem->initial_state; + } else { + transition_barrier.Transition.StateBefore = + dzn_image_layout_to_state(ibarrier->oldLayout, aspect); + } - if (transition_barrier.Transition.StateBefore == transition_barrier.Transition.StateAfter) - continue; + if (transition_barrier.Transition.StateBefore == transition_barrier.Transition.StateAfter) + continue; - /* some layouts map to the same states, and NOP-barriers are illegal */ - uint32_t layer_count = dzn_get_layer_count(image, range); - uint32_t level_count = dzn_get_level_count(image, range); - for (uint32_t layer = 0; layer < layer_count; layer++) { - for (uint32_t lvl = 0; lvl < level_count; lvl++) { - dzn_foreach_aspect(aspect, range->aspectMask) { + /* some layouts map to the same states, and NOP-barriers are illegal */ + uint32_t layer_count = dzn_get_layer_count(image, range); + uint32_t level_count = dzn_get_level_count(image, range); + for (uint32_t layer = 0; layer < layer_count; layer++) { + for (uint32_t lvl = 0; lvl < level_count; lvl++) { transition_barrier.Transition.Subresource = dzn_image_range_get_subresource_index(image, range, aspect, lvl, layer); cmdbuf->cmdlist->ResourceBarrier(1, &transition_barrier); @@ -930,7 +932,8 @@ dzn_cmd_buffer_clear_rects_with_copy(dzn_cmd_buffer *cmdbuf, }, }; - D3D12_RESOURCE_STATES dst_state = dzn_image_layout_to_state(layout); + D3D12_RESOURCE_STATES dst_state = + dzn_image_layout_to_state(layout, VK_IMAGE_ASPECT_COLOR_BIT); D3D12_RESOURCE_BARRIER barrier = { .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, @@ -1076,7 +1079,8 @@ dzn_cmd_buffer_clear_ranges_with_copy(dzn_cmd_buffer *cmdbuf, }, }; - D3D12_RESOURCE_STATES dst_state = dzn_image_layout_to_state(layout); + D3D12_RESOURCE_STATES dst_state = + dzn_image_layout_to_state(layout, VK_IMAGE_ASPECT_COLOR_BIT); D3D12_RESOURCE_BARRIER barrier = { .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, @@ -1282,7 +1286,8 @@ dzn_cmd_buffer_clear_color(dzn_cmd_buffer *cmdbuf, .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, .Transition = { .pResource = image->res, - .StateBefore = dzn_image_layout_to_state(layout), + .StateBefore = + dzn_image_layout_to_state(layout, VK_IMAGE_ASPECT_COLOR_BIT), .StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET, }, }; @@ -1344,23 +1349,34 @@ dzn_cmd_buffer_clear_zs(dzn_cmd_buffer *cmdbuf, flags |= D3D12_CLEAR_FLAG_STENCIL; for (uint32_t lvl = 0; lvl < level_count; lvl++) { - D3D12_RESOURCE_BARRIER barrier = { - .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, - .Transition = { - .pResource = image->res, - .StateBefore = dzn_image_layout_to_state(layout), - .StateAfter = D3D12_RESOURCE_STATE_DEPTH_WRITE, - }, - }; + uint32_t barrier_count = 0; + D3D12_RESOURCE_BARRIER barriers[2]; + VkImageAspectFlagBits barrier_aspects[2]; + + dzn_foreach_aspect(aspect, range->aspectMask) { + barrier_aspects[barrier_count] = aspect; + barriers[barrier_count] = D3D12_RESOURCE_BARRIER { + .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, + .Transition = { + .pResource = image->res, + .StateBefore = dzn_image_layout_to_state(layout, aspect), + .StateAfter = D3D12_RESOURCE_STATE_DEPTH_WRITE, + }, + }; - if (barrier.Transition.StateBefore != barrier.Transition.StateAfter) { + if (barriers[barrier_count].Transition.StateBefore != barriers[barrier_count].Transition.StateAfter) + barrier_count++; + } + + if (barrier_count > 0) { for (uint32_t layer = 0; layer < layer_count; layer++) { - dzn_foreach_aspect(aspect, range->aspectMask) { - barrier.Transition.Subresource = - dzn_image_range_get_subresource_index(image, range, aspect, lvl, layer); - cmdbuf->cmdlist->ResourceBarrier(1, &barrier); + for (uint32_t b = 0; b < barrier_count; b++) { + barriers[b].Transition.Subresource = + dzn_image_range_get_subresource_index(image, range, barrier_aspects[b], lvl, layer); } + + cmdbuf->cmdlist->ResourceBarrier(barrier_count, barriers); } } @@ -1370,15 +1386,17 @@ dzn_cmd_buffer_clear_zs(dzn_cmd_buffer *cmdbuf, zs->depth, zs->stencil, 0, NULL); - if (barrier.Transition.StateBefore != barrier.Transition.StateAfter) { - DZN_SWAP(barrier.Transition.StateBefore, barrier.Transition.StateAfter); + if (barrier_count > 0) { + for (uint32_t b = 0; b < barrier_count; b++) + DZN_SWAP(barriers[b].Transition.StateBefore, barriers[b].Transition.StateAfter); for (uint32_t layer = 0; layer < layer_count; layer++) { - dzn_foreach_aspect(aspect, range->aspectMask) { - barrier.Transition.Subresource = - dzn_image_range_get_subresource_index(image, range, aspect, lvl, layer); - cmdbuf->cmdlist->ResourceBarrier(1, &barrier); + for (uint32_t b = 0; b < barrier_count; b++) { + barriers[b].Transition.Subresource = + dzn_image_range_get_subresource_index(image, range, barrier_aspects[b], lvl, layer); } + + cmdbuf->cmdlist->ResourceBarrier(barrier_count, barriers); } } } @@ -1870,7 +1888,7 @@ dzn_cmd_buffer_blit_issue_barriers(dzn_cmd_buffer *cmdbuf, .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, .Transition = { .pResource = src->res, - .StateBefore = dzn_image_layout_to_state(src_layout), + .StateBefore = dzn_image_layout_to_state(src_layout, aspect), .StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, }, }, @@ -1879,7 +1897,7 @@ dzn_cmd_buffer_blit_issue_barriers(dzn_cmd_buffer *cmdbuf, .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, .Transition = { .pResource = dst->res, - .StateBefore = dzn_image_layout_to_state(dst_layout), + .StateBefore = dzn_image_layout_to_state(dst_layout, aspect), .StateAfter = ds ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_RENDER_TARGET, @@ -2094,17 +2112,34 @@ dzn_cmd_buffer_attachment_ref_transition(dzn_cmd_buffer *cmdbuf, if (att->before == att->during) return; - D3D12_RESOURCE_BARRIER barrier = { - .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, - .Transition = { - .pResource = image->res, - .Subresource = 0, // YOLO - .StateBefore = att->before, - .StateAfter = att->during, - }, + VkImageSubresourceRange subres { + .aspectMask = att->aspects, + .baseMipLevel = iview->vk.base_mip_level, + .levelCount = iview->vk.level_count, + .baseArrayLayer = iview->vk.base_array_layer, + .layerCount = iview->vk.layer_count, }; - cmdbuf->cmdlist->ResourceBarrier(1, &barrier); + + dzn_foreach_aspect(aspect, att->aspects) { + for (uint32_t lvl = 0; lvl < iview->vk.level_count; lvl++) { + for (uint32_t layer = 0; layer < iview->vk.layer_count; layer++) { + D3D12_RESOURCE_BARRIER barrier = { + .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, + .Transition = { + .pResource = image->res, + .Subresource = + dzn_image_range_get_subresource_index(image, &subres, aspect, lvl, layer), + .StateBefore = (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ? att->stencil.before : att->before, + .StateAfter = (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ? att->stencil.during : att->during, + }, + }; + + if (barrier.Transition.StateBefore != barrier.Transition.StateAfter) + cmdbuf->cmdlist->ResourceBarrier(1, &barrier); + } + } + } } static void @@ -2117,17 +2152,34 @@ dzn_cmd_buffer_attachment_transition(dzn_cmd_buffer *cmdbuf, if (att->last == att->after) return; - D3D12_RESOURCE_BARRIER barrier = { - .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, - .Transition = { - .pResource = image->res, - .Subresource = 0, // YOLO - .StateBefore = att->last, - .StateAfter = att->after, - }, + VkImageSubresourceRange subres { + .aspectMask = att->aspects, + .baseMipLevel = iview->vk.base_mip_level, + .levelCount = iview->vk.level_count, + .baseArrayLayer = iview->vk.base_array_layer, + .layerCount = iview->vk.layer_count, }; - cmdbuf->cmdlist->ResourceBarrier(1, &barrier); + + dzn_foreach_aspect(aspect, att->aspects) { + for (uint32_t lvl = 0; lvl < iview->vk.level_count; lvl++) { + for (uint32_t layer = 0; layer < iview->vk.layer_count; layer++) { + D3D12_RESOURCE_BARRIER barrier = { + .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, + .Transition = { + .pResource = image->res, + .Subresource = + dzn_image_range_get_subresource_index(image, &subres, aspect, lvl, layer), + .StateBefore = (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ? att->stencil.last : att->last, + .StateAfter = (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ? att->stencil.after : att->after, + }, + }; + + if (barrier.Transition.StateBefore != barrier.Transition.StateAfter) + cmdbuf->cmdlist->ResourceBarrier(1, &barrier); + } + } + } } static void diff --git a/src/microsoft/vulkan/dzn_image.cpp b/src/microsoft/vulkan/dzn_image.cpp index 79650b094e7..f2b1d9f0092 100644 --- a/src/microsoft/vulkan/dzn_image.cpp +++ b/src/microsoft/vulkan/dzn_image.cpp @@ -509,7 +509,7 @@ dzn_image_get_rtv_desc(const dzn_image *image, } D3D12_RESOURCE_STATES -dzn_image_layout_to_state(VkImageLayout layout) +dzn_image_layout_to_state(VkImageLayout layout, VkImageAspectFlagBits aspect) { switch (layout) { case VK_IMAGE_LAYOUT_PREINITIALIZED: @@ -536,6 +536,16 @@ dzn_image_layout_to_state(VkImageLayout layout) case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: return D3D12_RESOURCE_STATE_DEPTH_READ; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? + D3D12_RESOURCE_STATE_DEPTH_WRITE : + D3D12_RESOURCE_STATE_DEPTH_READ; + + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? + D3D12_RESOURCE_STATE_DEPTH_READ : + D3D12_RESOURCE_STATE_DEPTH_WRITE; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE; diff --git a/src/microsoft/vulkan/dzn_pass.cpp b/src/microsoft/vulkan/dzn_pass.cpp index 590d5137420..3da6e97b76f 100644 --- a/src/microsoft/vulkan/dzn_pass.cpp +++ b/src/microsoft/vulkan/dzn_pass.cpp @@ -68,9 +68,28 @@ dzn_CreateRenderPass2(VkDevice dev, attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR; } attachments[i].samples = attachment->samples; - attachments[i].before = dzn_image_layout_to_state(attachment->initialLayout); - attachments[i].after = dzn_image_layout_to_state(attachment->finalLayout); - attachments[i].last = attachments[i].before; + if (vk_format_has_stencil(attachment->format)) { + attachments[i].stencil.before = + dzn_image_layout_to_state(attachment->initialLayout, VK_IMAGE_ASPECT_STENCIL_BIT); + attachments[i].stencil.after = + dzn_image_layout_to_state(attachment->finalLayout, VK_IMAGE_ASPECT_STENCIL_BIT); + attachments[i].stencil.last = attachments[i].stencil.before; + } + + if (vk_format_has_depth(attachment->format)) { + attachments[i].before = + dzn_image_layout_to_state(attachment->initialLayout, VK_IMAGE_ASPECT_STENCIL_BIT); + attachments[i].after = + dzn_image_layout_to_state(attachment->finalLayout, VK_IMAGE_ASPECT_STENCIL_BIT); + attachments[i].last = attachments[i].before; + } else { + assert(vk_format_is_color(attachment->format)); + attachments[i].before = + dzn_image_layout_to_state(attachment->initialLayout, VK_IMAGE_ASPECT_COLOR_BIT); + attachments[i].after = + dzn_image_layout_to_state(attachment->finalLayout, VK_IMAGE_ASPECT_COLOR_BIT); + attachments[i].last = attachments[i].before; + } } assert(subpasses); @@ -85,10 +104,13 @@ dzn_CreateRenderPass2(VkDevice dev, uint32_t idx = subpass->pColorAttachments[j].attachment; subpasses[i].colors[j].idx = idx; if (idx != VK_ATTACHMENT_UNUSED) { + subpasses[i].colors[j].aspects = VK_IMAGE_ASPECT_COLOR_BIT; subpasses[i].colors[j].before = attachments[idx].last; subpasses[i].colors[j].during = - dzn_image_layout_to_state(subpass->pColorAttachments[j].layout); + dzn_image_layout_to_state(subpass->pColorAttachments[j].layout, + VK_IMAGE_ASPECT_COLOR_BIT); attachments[idx].last = subpasses[i].colors[j].during; + attachments[idx].aspects |= VK_IMAGE_ASPECT_COLOR_BIT; subpasses[i].color_count = j + 1; } @@ -97,10 +119,13 @@ dzn_CreateRenderPass2(VkDevice dev, VK_ATTACHMENT_UNUSED; subpasses[i].resolve[j].idx = idx; if (idx != VK_ATTACHMENT_UNUSED) { + subpasses[i].resolve[j].aspects = VK_IMAGE_ASPECT_COLOR_BIT; subpasses[i].resolve[j].before = attachments[idx].last; subpasses[i].resolve[j].during = - dzn_image_layout_to_state(subpass->pResolveAttachments[j].layout); + dzn_image_layout_to_state(subpass->pResolveAttachments[j].layout, + VK_IMAGE_ASPECT_COLOR_BIT); attachments[idx].last = subpasses[i].resolve[j].during; + attachments[idx].aspects |= VK_IMAGE_ASPECT_COLOR_BIT; } } @@ -109,10 +134,27 @@ dzn_CreateRenderPass2(VkDevice dev, uint32_t idx = subpass->pDepthStencilAttachment->attachment; subpasses[i].zs.idx = idx; if (idx != VK_ATTACHMENT_UNUSED) { + subpasses[i].zs.aspects = vk_format_aspects(attachments[idx].format); subpasses[i].zs.before = attachments[idx].last; - subpasses[i].zs.during = - dzn_image_layout_to_state(subpass->pDepthStencilAttachment->layout); + subpasses[i].zs.during = attachments[idx].last; + subpasses[i].zs.stencil.before = attachments[idx].stencil.last; + subpasses[i].zs.stencil.during = attachments[idx].stencil.last; + + if (subpasses[i].zs.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { + subpasses[i].zs.stencil.during = + dzn_image_layout_to_state(subpass->pDepthStencilAttachment->layout, + VK_IMAGE_ASPECT_STENCIL_BIT); + } + + if (subpasses[i].zs.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) { + subpasses[i].zs.during = + dzn_image_layout_to_state(subpass->pDepthStencilAttachment->layout, + VK_IMAGE_ASPECT_DEPTH_BIT); + } + attachments[idx].last = subpasses[i].zs.during; + attachments[idx].stencil.last = subpasses[i].zs.stencil.during; + attachments[idx].aspects |= subpasses[i].zs.aspects; } } @@ -121,10 +163,32 @@ dzn_CreateRenderPass2(VkDevice dev, uint32_t idx = subpass->pInputAttachments[j].attachment; subpasses[i].inputs[j].idx = idx; if (idx != VK_ATTACHMENT_UNUSED) { + subpasses[i].inputs[j].aspects = subpass->pInputAttachments[j].aspectMask; subpasses[i].inputs[j].before = attachments[idx].last; - subpasses[i].inputs[j].during = - dzn_image_layout_to_state(subpass->pInputAttachments[j].layout); + subpasses[i].inputs[j].during = attachments[idx].last; + subpasses[i].inputs[j].stencil.before = attachments[idx].stencil.last; + subpasses[i].inputs[j].stencil.during = attachments[idx].stencil.last; + + if (subpasses[i].inputs[j].aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { + subpasses[i].inputs[j].stencil.during = + dzn_image_layout_to_state(subpass->pInputAttachments[j].layout, + VK_IMAGE_ASPECT_STENCIL_BIT); + } + + if (subpasses[i].inputs[j].aspects & VK_IMAGE_ASPECT_DEPTH_BIT) { + subpasses[i].inputs[j].during = + dzn_image_layout_to_state(subpass->pInputAttachments[j].layout, + VK_IMAGE_ASPECT_DEPTH_BIT); + attachments[idx].last = subpasses[i].inputs[j].during; + } else if (subpasses[i].inputs[j].aspects == VK_IMAGE_ASPECT_COLOR_BIT) { + subpasses[i].inputs[j].during = + dzn_image_layout_to_state(subpass->pInputAttachments[j].layout, + VK_IMAGE_ASPECT_COLOR_BIT); + } + attachments[idx].last = subpasses[i].inputs[j].during; + attachments[idx].stencil.last = subpasses[i].inputs[j].stencil.during; + attachments[idx].aspects |= subpass->pInputAttachments[j].aspectMask; } } } diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h index 5d568bd9c11..fea0e5e53e6 100644 --- a/src/microsoft/vulkan/dzn_private.h +++ b/src/microsoft/vulkan/dzn_private.h @@ -329,12 +329,20 @@ struct dzn_attachment { bool stencil; }; } clear; + VkImageAspectFlags aspects; D3D12_RESOURCE_STATES before, last, after; + struct { + D3D12_RESOURCE_STATES before, last, after; + } stencil; }; struct dzn_attachment_ref { uint32_t idx; D3D12_RESOURCE_STATES before, during; + struct { + D3D12_RESOURCE_STATES before, during; + } stencil; + VkImageAspectFlags aspects; }; struct dzn_descriptor_state { @@ -789,7 +797,7 @@ dzn_image_get_rtv_desc(const dzn_image *image, uint32_t level); D3D12_RESOURCE_STATES -dzn_image_layout_to_state(VkImageLayout layout); +dzn_image_layout_to_state(VkImageLayout layout, VkImageAspectFlagBits aspect); uint32_t dzn_image_layers_get_subresource_index(const dzn_image *image, -- cgit v1.2.3