mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 05:52:11 +01:00
[dxvk] Fix potential layout transition issues with depth-stencil images
Some operations can operate on only one of the two aspects of a depth-stencil image. This fixes two possible issues: - Image memory barriers must be applied to all image aspects - VK_IMAGE_LAYOUT_UNDEFINED is no longer used as a source layout if the operation requiring the transition only uses one aspect
This commit is contained in:
parent
c370eea948
commit
8c65203ac2
@ -344,22 +344,23 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
|
VkImageLayout imageLayoutClear = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
m_barriers.accessImage(image, subresources,
|
m_barriers.accessImage(image, subresources,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
image->info().stages,
|
image->info().stages,
|
||||||
image->info().access,
|
image->info().access,
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutClear,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_cmd->cmdClearColorImage(image->handle(),
|
m_cmd->cmdClearColorImage(image->handle(),
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutClear, &value, 1, &subresources);
|
||||||
&value, 1, &subresources);
|
|
||||||
|
|
||||||
m_barriers.accessImage(image, subresources,
|
m_barriers.accessImage(image, subresources,
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutClear,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
image->info().layout,
|
image->info().layout,
|
||||||
@ -378,24 +379,29 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
|
VkImageLayout imageLayoutInitial = image->info().layout;
|
||||||
|
VkImageLayout imageLayoutClear = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
|
if (subresources.aspectMask == image->formatInfo()->aspectMask)
|
||||||
|
imageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
image, subresources,
|
image, subresources,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
imageLayoutInitial,
|
||||||
image->info().stages,
|
image->info().stages,
|
||||||
image->info().access,
|
image->info().access,
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutClear,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_cmd->cmdClearDepthStencilImage(image->handle(),
|
m_cmd->cmdClearDepthStencilImage(image->handle(),
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutClear, &value, 1, &subresources);
|
||||||
&value, 1, &subresources);
|
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
image, subresources,
|
image, subresources,
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutClear,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
image->info().layout,
|
image->info().layout,
|
||||||
@ -634,22 +640,31 @@ namespace dxvk {
|
|||||||
|
|
||||||
auto srcSlice = srcBuffer->subSlice(srcOffset, 0);
|
auto srcSlice = srcBuffer->subSlice(srcOffset, 0);
|
||||||
|
|
||||||
|
// We may copy to only one aspect of a depth-stencil image,
|
||||||
|
// but pipeline barriers need to have all aspect bits set
|
||||||
|
auto dstFormatInfo = dstImage->formatInfo();
|
||||||
|
|
||||||
VkImageSubresourceRange dstSubresourceRange = {
|
VkImageSubresourceRange dstSubresourceRange = {
|
||||||
dstSubresource.aspectMask,
|
dstFormatInfo->aspectMask,
|
||||||
dstSubresource.mipLevel, 1,
|
dstSubresource.mipLevel, 1,
|
||||||
dstSubresource.baseArrayLayer,
|
dstSubresource.baseArrayLayer,
|
||||||
dstSubresource.layerCount };
|
dstSubresource.layerCount };
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
|
// Initialize the image if the entire subresource is covered
|
||||||
|
VkImageLayout dstImageLayoutInitial = dstImage->info().layout;
|
||||||
|
VkImageLayout dstImageLayoutTransfer = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
|
if (dstImage->isFullSubresource(dstSubresource, dstExtent))
|
||||||
|
dstImageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
dstImage, dstSubresourceRange,
|
dstImage, dstSubresourceRange,
|
||||||
dstImage->mipLevelExtent(dstSubresource.mipLevel) == dstExtent
|
dstImageLayoutInitial,
|
||||||
? VK_IMAGE_LAYOUT_UNDEFINED
|
|
||||||
: dstImage->info().layout,
|
|
||||||
dstImage->info().stages,
|
dstImage->info().stages,
|
||||||
dstImage->info().access,
|
dstImage->info().access,
|
||||||
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
dstImageLayoutTransfer,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
@ -666,12 +681,12 @@ namespace dxvk {
|
|||||||
m_cmd->cmdCopyBufferToImage(
|
m_cmd->cmdCopyBufferToImage(
|
||||||
srcSlice.handle(),
|
srcSlice.handle(),
|
||||||
dstImage->handle(),
|
dstImage->handle(),
|
||||||
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
dstImageLayoutTransfer,
|
||||||
1, ©Region);
|
1, ©Region);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
dstImage, dstSubresourceRange,
|
dstImage, dstSubresourceRange,
|
||||||
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
dstImageLayoutTransfer,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
dstImage->info().layout,
|
dstImage->info().layout,
|
||||||
@ -849,20 +864,27 @@ namespace dxvk {
|
|||||||
|
|
||||||
auto dstSlice = dstBuffer->subSlice(dstOffset, 0);
|
auto dstSlice = dstBuffer->subSlice(dstOffset, 0);
|
||||||
|
|
||||||
|
// We may copy to only one aspect of a depth-stencil image,
|
||||||
|
// but pipeline barriers need to have all aspect bits set
|
||||||
|
auto srcFormatInfo = srcImage->formatInfo();
|
||||||
|
|
||||||
VkImageSubresourceRange srcSubresourceRange = {
|
VkImageSubresourceRange srcSubresourceRange = {
|
||||||
srcSubresource.aspectMask,
|
srcFormatInfo->aspectMask,
|
||||||
srcSubresource.mipLevel, 1,
|
srcSubresource.mipLevel, 1,
|
||||||
srcSubresource.baseArrayLayer,
|
srcSubresource.baseArrayLayer,
|
||||||
srcSubresource.layerCount };
|
srcSubresource.layerCount };
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
|
// Select a suitable image layout for the transfer op
|
||||||
|
VkImageLayout srcImageLayoutTransfer = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
srcImage, srcSubresourceRange,
|
srcImage, srcSubresourceRange,
|
||||||
srcImage->info().layout,
|
srcImage->info().layout,
|
||||||
srcImage->info().stages,
|
srcImage->info().stages,
|
||||||
srcImage->info().access,
|
srcImage->info().access,
|
||||||
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
srcImageLayoutTransfer,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_READ_BIT);
|
VK_ACCESS_TRANSFER_READ_BIT);
|
||||||
|
|
||||||
@ -878,13 +900,13 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_cmd->cmdCopyImageToBuffer(
|
m_cmd->cmdCopyImageToBuffer(
|
||||||
srcImage->handle(),
|
srcImage->handle(),
|
||||||
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
srcImageLayoutTransfer,
|
||||||
dstSlice.handle(),
|
dstSlice.handle(),
|
||||||
1, ©Region);
|
1, ©Region);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
srcImage, srcSubresourceRange,
|
srcImage, srcSubresourceRange,
|
||||||
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
srcImageLayoutTransfer,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_READ_BIT,
|
VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
srcImage->info().layout,
|
srcImage->info().layout,
|
||||||
@ -1457,14 +1479,19 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
|
// Initialize the image if the entire subresource is covered
|
||||||
|
VkImageLayout imageLayoutInitial = image->info().layout;
|
||||||
|
VkImageLayout imageLayoutTransfer = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
|
if (image->isFullSubresource(subresources, imageExtent))
|
||||||
|
imageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
image, subresourceRange,
|
image, subresourceRange,
|
||||||
image->mipLevelExtent(subresources.mipLevel) == imageExtent
|
imageLayoutInitial,
|
||||||
? VK_IMAGE_LAYOUT_UNDEFINED
|
|
||||||
: image->info().layout,
|
|
||||||
image->info().stages,
|
image->info().stages,
|
||||||
image->info().access,
|
image->info().access,
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutTransfer,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
@ -1482,13 +1509,12 @@ namespace dxvk {
|
|||||||
region.imageExtent = imageExtent;
|
region.imageExtent = imageExtent;
|
||||||
|
|
||||||
m_cmd->stagedBufferImageCopy(image->handle(),
|
m_cmd->stagedBufferImageCopy(image->handle(),
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutTransfer, region, slice);
|
||||||
region, slice);
|
|
||||||
|
|
||||||
// Transition image back into its optimal layout
|
// Transition image back into its optimal layout
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
image, subresourceRange,
|
image, subresourceRange,
|
||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
imageLayoutTransfer,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
image->info().layout,
|
image->info().layout,
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "dxvk_format.h"
|
#include "dxvk_format.h"
|
||||||
#include "dxvk_memory.h"
|
#include "dxvk_memory.h"
|
||||||
#include "dxvk_resource.h"
|
#include "dxvk_resource.h"
|
||||||
|
#include "dxvk_util.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -217,6 +218,21 @@ namespace dxvk {
|
|||||||
? VK_IMAGE_LAYOUT_GENERAL : layout;
|
? VK_IMAGE_LAYOUT_GENERAL : layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Checks whether a subresource is entirely covered
|
||||||
|
*
|
||||||
|
* This can be used to determine whether an image can or
|
||||||
|
* should be initialized with \c VK_IMAGE_LAYOUT_UNDEFINED.
|
||||||
|
* \param [in] subresource The image subresource
|
||||||
|
* \param [in] extent Image extent to check
|
||||||
|
*/
|
||||||
|
bool isFullSubresource(
|
||||||
|
const VkImageSubresourceLayers& subresource,
|
||||||
|
VkExtent3D extent) const {
|
||||||
|
return subresource.aspectMask == this->formatInfo()->aspectMask
|
||||||
|
&& extent == this->mipLevelExtent(subresource.mipLevel);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Rc<vk::DeviceFn> m_vkd;
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user