1
0
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:
Philip Rebohle 2025-03-10 20:40:02 +01:00
parent 292a0b498a
commit e0dea48dae
5 changed files with 103 additions and 34 deletions

View File

@ -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)

View File

@ -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(

View File

@ -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);

View File

@ -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);

View File

@ -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
*