[dxvk] Support depth-to-color image copies and vice versa

Fixes validation errors and depth of field effect in Neptunia VII
and potentially other games which do not use all depth images for
rendering.
This commit is contained in:
Philip Rebohle 2018-02-20 13:08:50 +01:00
parent be4ccc1260
commit 43dbc9f1d6
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
5 changed files with 92 additions and 37 deletions

View File

@ -286,15 +286,8 @@ namespace dxvk {
const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(dstTextureInfo->image->info().format);
const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcTextureInfo->image->info().format);
const VkImageSubresource dstSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
dstTextureInfo->image->info().mipLevels, DstSubresource);
const VkImageSubresource srcSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
srcTextureInfo->image->info().mipLevels, SrcSubresource);
const VkImageSubresource dstSubresource = GetSubresourceFromIndex(dstFormatInfo->aspectMask, dstTextureInfo->image->info().mipLevels, DstSubresource);
const VkImageSubresource srcSubresource = GetSubresourceFromIndex(srcFormatInfo->aspectMask, srcTextureInfo->image->info().mipLevels, SrcSubresource);
VkOffset3D srcOffset = { 0, 0, 0 };
VkOffset3D dstOffset = {
@ -391,13 +384,8 @@ namespace dxvk {
for (uint32_t i = 0; i < srcTextureInfo->image->info().mipLevels; i++) {
VkExtent3D extent = srcTextureInfo->image->mipLevelExtent(i);
const VkImageSubresourceLayers dstLayers = {
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
i, 0, dstTextureInfo->image->info().numLayers };
const VkImageSubresourceLayers srcLayers = {
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
i, 0, srcTextureInfo->image->info().numLayers };
const VkImageSubresourceLayers dstLayers = { dstFormatInfo->aspectMask, i, 0, dstTextureInfo->image->info().numLayers };
const VkImageSubresourceLayers srcLayers = { srcFormatInfo->aspectMask, i, 0, srcTextureInfo->image->info().numLayers };
EmitCs([
cDstImage = dstTextureInfo->image,

View File

@ -432,13 +432,11 @@ namespace dxvk {
dstImage->info().layout,
dstImage->info().stages,
dstImage->info().access);
m_barriers.accessBuffer(srcSlice,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
srcBuffer->info().stages,
srcBuffer->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(dstImage);
@ -478,7 +476,6 @@ namespace dxvk {
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
m_barriers.accessImage(
srcImage, srcSubresourceRange,
srcImage->info().layout,
@ -487,21 +484,75 @@ namespace dxvk {
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
m_barriers.recordCommands(m_cmd);
VkImageCopy imageRegion;
imageRegion.srcSubresource = srcSubresource;
imageRegion.srcOffset = srcOffset;
imageRegion.dstSubresource = dstSubresource;
imageRegion.dstOffset = dstOffset;
imageRegion.extent = extent;
m_cmd->cmdCopyImage(
srcImage->handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstImage->handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &imageRegion);
if (dstSubresource.aspectMask == srcSubresource.aspectMask) {
VkImageCopy imageRegion;
imageRegion.srcSubresource = srcSubresource;
imageRegion.srcOffset = srcOffset;
imageRegion.dstSubresource = dstSubresource;
imageRegion.dstOffset = dstOffset;
imageRegion.extent = extent;
m_cmd->cmdCopyImage(
srcImage->handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstImage->handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &imageRegion);
} else {
const VkDeviceSize transferBufferSize = std::max(
util::computeImageDataSize(dstImage->info().format, extent),
util::computeImageDataSize(srcImage->info().format, extent));
// TODO optimize away buffer creation
DxvkBufferCreateInfo tmpBufferInfo;
tmpBufferInfo.size = transferBufferSize;
tmpBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
tmpBufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
tmpBufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;
Rc<DxvkBuffer> tmpBuffer = m_device->createBuffer(
tmpBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
DxvkPhysicalBufferSlice tmpSlice = tmpBuffer->slice();
VkBufferImageCopy bufferImageCopy;
bufferImageCopy.bufferOffset = tmpSlice.offset();
bufferImageCopy.bufferRowLength = 0;
bufferImageCopy.bufferImageHeight = 0;
bufferImageCopy.imageSubresource = srcSubresource;
bufferImageCopy.imageOffset = srcOffset;
bufferImageCopy.imageExtent = extent;
m_cmd->cmdCopyImageToBuffer(
srcImage->handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
tmpSlice.handle(), 1, &bufferImageCopy);
m_barriers.accessBuffer(tmpSlice,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
m_barriers.recordCommands(m_cmd);
bufferImageCopy.imageSubresource = dstSubresource;
bufferImageCopy.imageOffset = dstOffset;
m_cmd->cmdCopyBufferToImage(
tmpSlice.handle(), dstImage->handle(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &bufferImageCopy);
m_barriers.accessBuffer(tmpSlice,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
tmpBuffer->info().stages,
tmpBuffer->info().access);
m_cmd->trackResource(tmpSlice.resource());
}
m_barriers.accessImage(
dstImage, dstSubresourceRange,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
@ -510,7 +561,6 @@ namespace dxvk {
dstImage->info().layout,
dstImage->info().stages,
dstImage->info().access);
m_barriers.accessImage(
srcImage, srcSubresourceRange,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
@ -519,7 +569,6 @@ namespace dxvk {
srcImage->info().layout,
srcImage->info().stages,
srcImage->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(dstImage);
@ -577,13 +626,11 @@ namespace dxvk {
srcImage->info().layout,
srcImage->info().stages,
srcImage->info().access);
m_barriers.accessBuffer(dstSlice,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
dstBuffer->info().stages,
dstBuffer->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(srcImage);

View File

@ -634,6 +634,8 @@ namespace dxvk {
void eraseActiveQuery(
const DxvkQueryRevision& query);
Rc<DxvkBuffer> getTransferBuffer(VkDeviceSize size);
};
}

View File

@ -1,5 +1,6 @@
#include <cstring>
#include "dxvk_format.h"
#include "dxvk_util.h"
namespace dxvk::util {
@ -68,4 +69,10 @@ namespace dxvk::util {
}
}
VkDeviceSize computeImageDataSize(VkFormat format, VkExtent3D extent) {
const DxvkFormatInfo* formatInfo = imageFormatInfo(format);
return formatInfo->elementSize * flattenImageExtent(computeBlockCount(extent, formatInfo->blockSize));
}
}

View File

@ -66,6 +66,17 @@ namespace dxvk::util {
return extent.width * extent.height * extent.depth;
}
/**
* \brief Computes image data size, in bytes
*
* Convenience method that can be used to compute the number
* of bytes required to store image data in a given format.
* \param [in] format The image format
* \param [in] extent Image size, in pixels
* \returns Data size, in bytes
*/
VkDeviceSize computeImageDataSize(VkFormat format, VkExtent3D extent);
}