mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 04:29:15 +01:00
[dxvk] Extend resolveImage to support depth-stencil resolves
Also require the format to be defined.
This commit is contained in:
parent
292a0b498a
commit
e0dea48dae
@ -909,7 +909,7 @@ namespace dxvk {
|
||||
cDstImage->mipLevelExtent(cDstLayers.mipLevel));
|
||||
});
|
||||
} else {
|
||||
const VkFormat format = m_parent->LookupFormat(
|
||||
VkFormat format = m_parent->LookupFormat(
|
||||
Format, DXGI_VK_FORMAT_MODE_ANY).Format;
|
||||
|
||||
EmitCs([
|
||||
@ -919,6 +919,8 @@ namespace dxvk {
|
||||
cSrcSubres = srcSubresourceLayers,
|
||||
cFormat = format
|
||||
] (DxvkContext* ctx) {
|
||||
VkFormat format = cFormat ? cFormat : cSrcImage->info().format;
|
||||
|
||||
VkImageResolve region;
|
||||
region.srcSubresource = cSrcSubres;
|
||||
region.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
@ -926,7 +928,8 @@ namespace dxvk {
|
||||
region.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
region.extent = cDstImage->mipLevelExtent(cDstSubres.mipLevel);
|
||||
|
||||
ctx->resolveImage(cDstImage, cSrcImage, region, cFormat);
|
||||
ctx->resolveImage(cDstImage, cSrcImage, region, format,
|
||||
getDefaultResolveMode(format), VK_RESOLVE_MODE_NONE);
|
||||
});
|
||||
|
||||
if constexpr (!IsDeferred)
|
||||
|
@ -1353,9 +1353,8 @@ namespace dxvk {
|
||||
cRegion = region
|
||||
] (DxvkContext* ctx) {
|
||||
if (cRegion.srcSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->resolveImage(
|
||||
cDstImage, cSrcImage, cRegion,
|
||||
VK_FORMAT_UNDEFINED);
|
||||
ctx->resolveImage(cDstImage, cSrcImage, cRegion, cSrcImage->info().format,
|
||||
VK_RESOLVE_MODE_AVERAGE_BIT, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
|
||||
}
|
||||
else {
|
||||
ctx->resolveDepthStencilImage(
|
||||
@ -4935,6 +4934,8 @@ namespace dxvk {
|
||||
cResolveImage = mappedImage,
|
||||
cSubresource = subresourceLayers
|
||||
] (DxvkContext* ctx) {
|
||||
VkFormat format = cMainImage->info().format;
|
||||
|
||||
VkImageResolve region;
|
||||
region.srcSubresource = cSubresource;
|
||||
region.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
@ -4943,9 +4944,8 @@ namespace dxvk {
|
||||
region.extent = cMainImage->mipLevelExtent(cSubresource.mipLevel);
|
||||
|
||||
if (cSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->resolveImage(
|
||||
cResolveImage, cMainImage, region,
|
||||
cMainImage->info().format);
|
||||
ctx->resolveImage(cResolveImage, cMainImage, region, format,
|
||||
getDefaultResolveMode(format), VK_RESOLVE_MODE_NONE);
|
||||
}
|
||||
else {
|
||||
ctx->resolveDepthStencilImage(
|
||||
|
@ -327,9 +327,8 @@ namespace dxvk {
|
||||
resolveRegion.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
resolveRegion.extent = cSrcImage->info().extent;
|
||||
|
||||
ctx->resolveImage(
|
||||
cDstImage, cSrcImage,
|
||||
resolveRegion, VK_FORMAT_UNDEFINED);
|
||||
ctx->resolveImage(cDstImage, cSrcImage, resolveRegion,
|
||||
cSrcImage->info().format, VK_RESOLVE_MODE_AVERAGE_BIT, VK_RESOLVE_MODE_NONE);
|
||||
});
|
||||
|
||||
srcImage = std::move(resolvedSrc);
|
||||
|
@ -1939,34 +1939,97 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageResolve& region,
|
||||
VkFormat format) {
|
||||
if (format == VK_FORMAT_UNDEFINED)
|
||||
format = srcImage->info().format;
|
||||
VkFormat format,
|
||||
VkResolveModeFlagBits mode,
|
||||
VkResolveModeFlagBits stencilMode) {
|
||||
auto formatInfo = lookupFormatInfo(format);
|
||||
|
||||
if (resolveImageInline(dstImage, srcImage, region, format, VK_RESOLVE_MODE_AVERAGE_BIT, VK_RESOLVE_MODE_NONE))
|
||||
// Normalize resolve modes to available subresources
|
||||
VkImageAspectFlags aspects = region.srcSubresource.aspectMask
|
||||
& region.dstSubresource.aspectMask;
|
||||
|
||||
if (!(aspects & VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
stencilMode = VK_RESOLVE_MODE_NONE;
|
||||
|
||||
// No-op, but legal
|
||||
if (!mode && !stencilMode)
|
||||
return;
|
||||
|
||||
// Check whether the given resolve modes are supported for render pass resolves
|
||||
bool useFb = false;
|
||||
|
||||
if (formatInfo->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
const auto& properties = m_device->properties().vk12;
|
||||
|
||||
useFb |= (properties.supportedDepthResolveModes & mode) != mode
|
||||
|| (properties.supportedStencilResolveModes & stencilMode) != stencilMode;
|
||||
|
||||
if (mode != stencilMode && (formatInfo->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
useFb |= (!mode || !stencilMode)
|
||||
? !properties.independentResolveNone
|
||||
: !properties.independentResolve;
|
||||
}
|
||||
} else {
|
||||
// For color images, only the default mode is supported
|
||||
useFb |= mode != getDefaultResolveMode(formatInfo);
|
||||
}
|
||||
|
||||
// Also fall back to framebuffer path if this is a partial resolve,
|
||||
// or if two depth-stencil images are not format-compatible.
|
||||
if (!useFb) {
|
||||
useFb |= !dstImage->isFullSubresource(region.dstSubresource, region.extent)
|
||||
|| !srcImage->isFullSubresource(region.srcSubresource, region.extent);
|
||||
|
||||
if (formatInfo->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
useFb |= dstImage->info().format != srcImage->info().format;
|
||||
}
|
||||
|
||||
// Ensure that we can actually use both images as intended
|
||||
DxvkImageUsageInfo dstUsage = { };
|
||||
dstUsage.viewFormatCount = 1;
|
||||
dstUsage.viewFormats = &format;
|
||||
|
||||
if (formatInfo->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
dstUsage.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
dstUsage.stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
dstUsage.access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
} else {
|
||||
dstUsage.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
dstUsage.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dstUsage.access = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
}
|
||||
|
||||
DxvkImageUsageInfo srcUsage = dstUsage;
|
||||
|
||||
if (useFb) {
|
||||
srcUsage.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
srcUsage.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
srcUsage.access = VK_ACCESS_SHADER_READ_BIT;
|
||||
}
|
||||
|
||||
bool useHw = !ensureImageCompatibility(dstImage, dstUsage)
|
||||
|| !ensureImageCompatibility(srcImage, srcUsage);
|
||||
|
||||
// If possible, fold resolve into active render pass
|
||||
if (!useHw && !useFb && resolveImageInline(dstImage, srcImage, region, format, mode, stencilMode))
|
||||
return;
|
||||
|
||||
this->spillRenderPass(true);
|
||||
this->prepareImage(dstImage, vk::makeSubresourceRange(region.dstSubresource));
|
||||
this->prepareImage(srcImage, vk::makeSubresourceRange(region.srcSubresource));
|
||||
|
||||
auto formatInfo = lookupFormatInfo(format);
|
||||
|
||||
bool useRp = srcImage->info().format != format
|
||||
|| dstImage->info().format != format;
|
||||
|
||||
useRp |= (srcImage->info().usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
|
||||
&& (dstImage->info().usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||
|
||||
if (useRp) {
|
||||
// Work out resolve mode based on format properties. For color images,
|
||||
// we must use AVERAGE unless the resolve uses an integer format.
|
||||
VkResolveModeFlagBits mode = getDefaultResolveMode(formatInfo);
|
||||
|
||||
this->resolveImageRp(dstImage, srcImage, region,
|
||||
format, mode, mode);
|
||||
} else {
|
||||
if (unlikely(useHw)) {
|
||||
// Only used as a fallback if we can't use the images any other way,
|
||||
// format and resolve mode might not match what the app requests.
|
||||
this->resolveImageHw(dstImage, srcImage, region);
|
||||
} else if (unlikely(useFb)) {
|
||||
// Only used for weird resolve modes or partial resolves
|
||||
this->resolveImageFb(dstImage, srcImage,
|
||||
region, format, mode, stencilMode);
|
||||
} else {
|
||||
// Default path, use a resolve attachment
|
||||
this->resolveImageRp(dstImage, srcImage,
|
||||
region, format, mode, stencilMode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2486,7 +2549,7 @@ namespace dxvk {
|
||||
attachment.view->image(), region, resolve.depthMode, resolve.stencilMode);
|
||||
} else {
|
||||
resolveImage(resolve.imageView->image(), attachment.view->image(),
|
||||
region, attachment.view->info().format);
|
||||
region, attachment.view->info().format, resolve.depthMode, resolve.stencilMode);
|
||||
}
|
||||
|
||||
resolve.layerMask &= ~0u << (layerIndex + layerCount);
|
||||
|
@ -1046,13 +1046,17 @@ namespace dxvk {
|
||||
* \param [in] srcImage Source image
|
||||
* \param [in] region Region to resolve
|
||||
* \param [in] format Format for the resolve operation
|
||||
* \param [in] mode Image resolve mode
|
||||
* \param [in] stencilMode Stencil resolve mode
|
||||
*/
|
||||
void resolveImage(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageResolve& region,
|
||||
VkFormat format);
|
||||
|
||||
VkFormat format,
|
||||
VkResolveModeFlagBits mode,
|
||||
VkResolveModeFlagBits stencilMode);
|
||||
|
||||
/**
|
||||
* \brief Resolves a multisampled depth-stencil resource
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user