mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 04:08:52 +01:00
[dxvk] Support arbitrary source formats for color<->depth copies
Fixes rendering bugs in War Thunder.
This commit is contained in:
parent
c5aeb0f87a
commit
70e34dc31c
@ -3563,41 +3563,39 @@ namespace dxvk {
|
|||||||
VkImageSubresourceLayers srcSubresource,
|
VkImageSubresourceLayers srcSubresource,
|
||||||
VkOffset3D srcOffset,
|
VkOffset3D srcOffset,
|
||||||
VkExtent3D extent) {
|
VkExtent3D extent) {
|
||||||
VkFormat viewFormat = m_common->metaCopy().getCopyDestinationFormat(
|
DxvkMetaCopyFormats viewFormats = m_common->metaCopy().getFormats(
|
||||||
dstSubresource.aspectMask,
|
dstImage->info().format, dstSubresource.aspectMask,
|
||||||
srcSubresource.aspectMask,
|
srcImage->info().format, srcSubresource.aspectMask);
|
||||||
srcImage->info().format);
|
|
||||||
|
|
||||||
if (!viewFormat) {
|
|
||||||
Logger::err("DxvkContext: copyImageFb: Unsupported format");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usually we should be able to draw directly to the destination image,
|
// Usually we should be able to draw directly to the destination image,
|
||||||
// but in some cases this might not be possible, e.g. if when copying
|
// but in some cases this might not be possible, e.g. if when copying
|
||||||
// from something like D32_SFLOAT to RGBA8_UNORM. In those situations,
|
// from something like D32_SFLOAT to RGBA8_UNORM. In those situations,
|
||||||
// create a temporary image to draw to, and then copy to the actual
|
// create a temporary image to draw to, and then copy to the actual
|
||||||
// destination image using a regular Vulkan transfer function.
|
// destination image using a regular Vulkan transfer function.
|
||||||
bool useDirectCopy = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
bool dstIsCompatible = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
||||||
&& (dstImage->isViewCompatible(viewFormat));
|
&& (dstImage->isViewCompatible(viewFormats.dstFormat));
|
||||||
|
bool srcIsCompatible = (srcImage->info().usage & (VK_IMAGE_USAGE_SAMPLED_BIT))
|
||||||
|
&& (srcImage->isViewCompatible(viewFormats.srcFormat));
|
||||||
|
|
||||||
if (useDirectCopy) {
|
if (dstIsCompatible && srcIsCompatible) {
|
||||||
this->copyImageFbDirect(
|
this->copyImageFbDirect(
|
||||||
dstImage, dstSubresource, dstOffset, viewFormat,
|
dstImage, dstSubresource, dstOffset, viewFormats.dstFormat,
|
||||||
srcImage, srcSubresource, srcOffset, extent);
|
srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent);
|
||||||
} else {
|
} else if (dstIsCompatible || srcIsCompatible) {
|
||||||
DxvkImageCreateInfo imageInfo = dstImage->info();
|
DxvkImageCreateInfo imageInfo = dstImage->info();
|
||||||
imageInfo.format = viewFormat;
|
|
||||||
imageInfo.flags = 0;
|
imageInfo.flags = 0;
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
imageInfo.extent = extent;
|
imageInfo.extent = extent;
|
||||||
imageInfo.numLayers = dstSubresource.layerCount;
|
|
||||||
imageInfo.mipLevels = 1;
|
imageInfo.mipLevels = 1;
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
imageInfo.viewFormatCount = 0;
|
||||||
|
|
||||||
|
if (!dstIsCompatible) {
|
||||||
|
imageInfo.format = viewFormats.dstFormat;
|
||||||
|
imageInfo.numLayers = dstSubresource.layerCount;
|
||||||
|
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
imageInfo.viewFormatCount = 0;
|
|
||||||
|
|
||||||
if (dstImage->formatInfo()->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
if (dstImage->formatInfo()->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||||
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
@ -3609,23 +3607,46 @@ namespace dxvk {
|
|||||||
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
}
|
}
|
||||||
|
} else /* if (!srcIsCompatible) */ {
|
||||||
|
imageInfo.format = viewFormats.srcFormat;
|
||||||
|
imageInfo.numLayers = srcSubresource.layerCount;
|
||||||
|
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
imageInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
Rc<DxvkImage> tmpImage = m_device->createImage(imageInfo,
|
Rc<DxvkImage> tmpImage = m_device->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
VkImageSubresourceLayers tmpSubresource = dstSubresource;
|
VkImageSubresourceLayers tmpSubresource = { };
|
||||||
|
tmpSubresource.aspectMask = tmpImage->formatInfo()->aspectMask;
|
||||||
tmpSubresource.mipLevel = 0;
|
tmpSubresource.mipLevel = 0;
|
||||||
tmpSubresource.baseArrayLayer = 0;
|
tmpSubresource.baseArrayLayer = 0;
|
||||||
|
tmpSubresource.layerCount = imageInfo.numLayers;
|
||||||
|
|
||||||
VkOffset3D tmpOffset = { 0, 0, 0 };
|
VkOffset3D tmpOffset = { 0, 0, 0 };
|
||||||
|
|
||||||
|
if (!dstIsCompatible) {
|
||||||
this->copyImageFbDirect(
|
this->copyImageFbDirect(
|
||||||
tmpImage, tmpSubresource, tmpOffset, viewFormat,
|
tmpImage, tmpSubresource, tmpOffset, viewFormats.dstFormat,
|
||||||
srcImage, srcSubresource, srcOffset, extent);
|
srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent);
|
||||||
|
|
||||||
this->copyImageHw(
|
this->copyImageHw(
|
||||||
dstImage, dstSubresource, dstOffset,
|
dstImage, dstSubresource, dstOffset,
|
||||||
tmpImage, tmpSubresource, tmpOffset, extent);
|
tmpImage, tmpSubresource, tmpOffset, extent);
|
||||||
|
} else /* if (!srcIsCompatible) */ {
|
||||||
|
this->copyImageHw(
|
||||||
|
tmpImage, tmpSubresource, tmpOffset,
|
||||||
|
srcImage, srcSubresource, srcOffset, extent);
|
||||||
|
|
||||||
|
this->copyImageFbDirect(
|
||||||
|
dstImage, dstSubresource, dstOffset, viewFormats.dstFormat,
|
||||||
|
tmpImage, tmpSubresource, tmpOffset, viewFormats.srcFormat, extent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger::err(str::format("DxvkContext: copyImageFb: Unsupported operation:\n"
|
||||||
|
" srcFormat = ", srcImage->info().format, " (aspect ", srcSubresource.aspectMask, ")\n",
|
||||||
|
" dstFormat = ", dstImage->info().format, " (aspect ", dstSubresource.aspectMask, ")"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3638,6 +3659,7 @@ namespace dxvk {
|
|||||||
const Rc<DxvkImage>& srcImage,
|
const Rc<DxvkImage>& srcImage,
|
||||||
VkImageSubresourceLayers srcSubresource,
|
VkImageSubresourceLayers srcSubresource,
|
||||||
VkOffset3D srcOffset,
|
VkOffset3D srcOffset,
|
||||||
|
VkFormat srcFormat,
|
||||||
VkExtent3D extent) {
|
VkExtent3D extent) {
|
||||||
this->invalidateState();
|
this->invalidateState();
|
||||||
|
|
||||||
@ -3701,8 +3723,6 @@ namespace dxvk {
|
|||||||
m_execAcquires.recordCommands(m_cmd);
|
m_execAcquires.recordCommands(m_cmd);
|
||||||
|
|
||||||
// Create source and destination image views
|
// Create source and destination image views
|
||||||
VkFormat srcFormat = srcImage->info().format;
|
|
||||||
|
|
||||||
Rc<DxvkMetaCopyViews> views = new DxvkMetaCopyViews(m_device->vkd(),
|
Rc<DxvkMetaCopyViews> views = new DxvkMetaCopyViews(m_device->vkd(),
|
||||||
dstImage, dstSubresource, dstFormat,
|
dstImage, dstSubresource, dstFormat,
|
||||||
srcImage, srcSubresource, srcFormat);
|
srcImage, srcSubresource, srcFormat);
|
||||||
|
@ -1506,6 +1506,7 @@ namespace dxvk {
|
|||||||
const Rc<DxvkImage>& srcImage,
|
const Rc<DxvkImage>& srcImage,
|
||||||
VkImageSubresourceLayers srcSubresource,
|
VkImageSubresourceLayers srcSubresource,
|
||||||
VkOffset3D srcOffset,
|
VkOffset3D srcOffset,
|
||||||
|
VkFormat srcFormat,
|
||||||
VkExtent3D extent);
|
VkExtent3D extent);
|
||||||
|
|
||||||
bool copyImageClear(
|
bool copyImageClear(
|
||||||
|
@ -120,32 +120,29 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkFormat DxvkMetaCopyObjects::getCopyDestinationFormat(
|
DxvkMetaCopyFormats DxvkMetaCopyObjects::getFormats(
|
||||||
|
VkFormat dstFormat,
|
||||||
VkImageAspectFlags dstAspect,
|
VkImageAspectFlags dstAspect,
|
||||||
VkImageAspectFlags srcAspect,
|
VkFormat srcFormat,
|
||||||
VkFormat srcFormat) const {
|
VkImageAspectFlags srcAspect) const {
|
||||||
if (srcAspect == dstAspect)
|
if (dstAspect == srcAspect)
|
||||||
return srcFormat;
|
return { dstFormat, srcFormat };
|
||||||
|
|
||||||
if (dstAspect == VK_IMAGE_ASPECT_COLOR_BIT
|
if (dstAspect == VK_IMAGE_ASPECT_COLOR_BIT && srcAspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
||||||
&& srcAspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
||||||
switch (srcFormat) {
|
switch (srcFormat) {
|
||||||
case VK_FORMAT_D16_UNORM: return VK_FORMAT_R16_UNORM;
|
case VK_FORMAT_D16_UNORM: return { VK_FORMAT_R16_UNORM, VK_FORMAT_D16_UNORM };
|
||||||
case VK_FORMAT_D32_SFLOAT: return VK_FORMAT_R32_SFLOAT;
|
case VK_FORMAT_D32_SFLOAT: return { VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT };
|
||||||
default: return VK_FORMAT_UNDEFINED;
|
default: return { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
|
||||||
|
}
|
||||||
|
} else if (dstAspect == VK_IMAGE_ASPECT_DEPTH_BIT && srcAspect == VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||||
|
switch (dstFormat) {
|
||||||
|
case VK_FORMAT_D16_UNORM: return { VK_FORMAT_D16_UNORM, VK_FORMAT_R16_UNORM };
|
||||||
|
case VK_FORMAT_D32_SFLOAT: return { VK_FORMAT_D32_SFLOAT, VK_FORMAT_R32_SFLOAT };
|
||||||
|
default: return { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dstAspect == VK_IMAGE_ASPECT_DEPTH_BIT
|
return { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
|
||||||
&& srcAspect == VK_IMAGE_ASPECT_COLOR_BIT) {
|
|
||||||
switch (srcFormat) {
|
|
||||||
case VK_FORMAT_R16_UNORM: return VK_FORMAT_D16_UNORM;
|
|
||||||
case VK_FORMAT_R32_SFLOAT: return VK_FORMAT_D32_SFLOAT;
|
|
||||||
default: return VK_FORMAT_UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return VK_FORMAT_UNDEFINED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,14 @@ namespace dxvk {
|
|||||||
VkExtent2D srcSize;
|
VkExtent2D srcSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Pair of view formats for copy operation
|
||||||
|
*/
|
||||||
|
struct DxvkMetaCopyFormats {
|
||||||
|
VkFormat dstFormat;
|
||||||
|
VkFormat srcFormat;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Copy pipeline
|
* \brief Copy pipeline
|
||||||
*
|
*
|
||||||
@ -122,13 +130,17 @@ namespace dxvk {
|
|||||||
* Returns the color format that we need to use
|
* Returns the color format that we need to use
|
||||||
* as the destination image view format in case
|
* as the destination image view format in case
|
||||||
* of depth to color image copies.
|
* of depth to color image copies.
|
||||||
* \param [in] format Depth format
|
* \param [in] dstFormat Destination image format
|
||||||
|
* \param [in] dstAspect Destination aspect mask
|
||||||
|
* \param [in] srcFormat Source image format
|
||||||
|
* \param [in] srcAspect Source aspect mask
|
||||||
* \returns Corresponding color format
|
* \returns Corresponding color format
|
||||||
*/
|
*/
|
||||||
VkFormat getCopyDestinationFormat(
|
DxvkMetaCopyFormats getFormats(
|
||||||
|
VkFormat dstFormat,
|
||||||
VkImageAspectFlags dstAspect,
|
VkImageAspectFlags dstAspect,
|
||||||
VkImageAspectFlags srcAspect,
|
VkFormat srcFormat,
|
||||||
VkFormat srcFormat) const;
|
VkImageAspectFlags srcAspect) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates pipeline for meta copy operation
|
* \brief Creates pipeline for meta copy operation
|
||||||
|
Loading…
Reference in New Issue
Block a user