mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-26 01:54:15 +01:00
[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:
parent
be4ccc1260
commit
43dbc9f1d6
@ -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,
|
||||
|
@ -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,9 +484,9 @@ namespace dxvk {
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
|
||||
if (dstSubresource.aspectMask == srcSubresource.aspectMask) {
|
||||
VkImageCopy imageRegion;
|
||||
imageRegion.srcSubresource = srcSubresource;
|
||||
imageRegion.srcOffset = srcOffset;
|
||||
@ -501,6 +498,60 @@ namespace dxvk {
|
||||
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,
|
||||
@ -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);
|
||||
|
@ -634,6 +634,8 @@ namespace dxvk {
|
||||
void eraseActiveQuery(
|
||||
const DxvkQueryRevision& query);
|
||||
|
||||
Rc<DxvkBuffer> getTransferBuffer(VkDeviceSize size);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user