1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[dxvk] Refactor meta image copies

This commit is contained in:
Philip Rebohle 2024-09-28 11:52:08 +02:00 committed by Philip Rebohle
parent ae90e74a5a
commit 2c176f4950
4 changed files with 72 additions and 169 deletions

View File

@ -3747,105 +3747,33 @@ namespace dxvk {
dstImage->info().format, dstSubresource.aspectMask,
srcImage->info().format, srcSubresource.aspectMask);
// 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
// from something like D32_SFLOAT to RGBA8_UNORM. In those situations,
// create a temporary image to draw to, and then copy to the actual
// destination image using a regular Vulkan transfer function.
bool dstIsCompatible = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
&& (dstImage->isViewCompatible(viewFormats.dstFormat));
bool srcIsCompatible = (srcImage->info().usage & (VK_IMAGE_USAGE_SAMPLED_BIT))
&& (srcImage->isViewCompatible(viewFormats.srcFormat));
// Guarantee that we can render to or sample the images
DxvkImageUsageInfo dstUsage = { };
dstUsage.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
dstUsage.viewFormatCount = 1;
dstUsage.viewFormats = &viewFormats.dstFormat;
if (dstIsCompatible && srcIsCompatible) {
this->copyImageFbDirect(
dstImage, dstSubresource, dstOffset, viewFormats.dstFormat,
srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent);
} else if (dstIsCompatible || srcIsCompatible) {
DxvkImageCreateInfo imageInfo = dstImage->info();
imageInfo.flags = 0;
imageInfo.extent = extent;
imageInfo.mipLevels = 1;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.viewFormatCount = 0;
if (dstImage->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
dstUsage.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
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.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
DxvkImageUsageInfo srcUsage = { };
srcUsage.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
srcUsage.viewFormatCount = 1;
srcUsage.viewFormats = &viewFormats.srcFormat;
if (dstImage->formatInfo()->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
} else {
imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_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, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkImageSubresourceLayers tmpSubresource = { };
tmpSubresource.aspectMask = tmpImage->formatInfo()->aspectMask;
tmpSubresource.mipLevel = 0;
tmpSubresource.baseArrayLayer = 0;
tmpSubresource.layerCount = imageInfo.numLayers;
VkOffset3D tmpOffset = { 0, 0, 0 };
if (!dstIsCompatible) {
this->copyImageFbDirect(
tmpImage, tmpSubresource, tmpOffset, viewFormats.dstFormat,
srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent);
this->copyImageHw(
dstImage, dstSubresource, dstOffset,
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, ")"));
if (!ensureImageCompatibility(dstImage, dstUsage)
|| !ensureImageCompatibility(srcImage, srcUsage)) {
Logger::err(str::format("DxvkContext: copyImageFb: Unsupported images:"
"\n dst format: ", dstImage->info().format,
"\n src format: ", srcImage->info().format));
return;
}
}
void DxvkContext::copyImageFbDirect(
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
VkOffset3D dstOffset,
VkFormat dstFormat,
const Rc<DxvkImage>& srcImage,
VkImageSubresourceLayers srcSubresource,
VkOffset3D srcOffset,
VkFormat srcFormat,
VkExtent3D extent) {
this->invalidateState();
auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource);
auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresource);
if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write)
|| m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write))
m_execBarriers.recordCommands(m_cmd);
@ -3903,22 +3831,27 @@ namespace dxvk {
m_execAcquires.recordCommands(m_cmd);
// Create source and destination image views
Rc<DxvkMetaCopyViews> views = new DxvkMetaCopyViews(m_device->vkd(),
dstImage, dstSubresource, dstFormat,
srcImage, srcSubresource, srcFormat);
DxvkMetaCopyViews views(
dstImage, dstSubresource, viewFormats.dstFormat,
srcImage, srcSubresource, viewFormats.srcFormat);
// Create pipeline for the copy operation
DxvkMetaCopyPipeline pipeInfo = m_common->metaCopy().getPipeline(
views->getSrcViewType(), dstFormat, dstImage->info().sampleCount);
views.srcImageView->info().viewType, viewFormats.dstFormat, dstImage->info().sampleCount);
// Create and initialize descriptor set
VkDescriptorSet descriptorSet = m_descriptorPool->alloc(pipeInfo.dsetLayout);
std::array<VkDescriptorImageInfo, 2> descriptorImages = {{
{ VK_NULL_HANDLE, views->getSrcView(), srcLayout },
{ VK_NULL_HANDLE, views->getSrcStencilView(), srcLayout },
{ VK_NULL_HANDLE, views.srcImageView->handle(), srcLayout },
{ VK_NULL_HANDLE, VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED },
}};
if (views.srcStencilView) {
descriptorImages[1].imageView = views.srcStencilView->handle();
descriptorImages[1].imageLayout = srcLayout;
}
std::array<VkWriteDescriptorSet, 2> descriptorWrites;
for (uint32_t i = 0; i < descriptorWrites.size(); i++) {
@ -3950,7 +3883,7 @@ namespace dxvk {
VkExtent3D mipExtent = dstImage->mipLevelExtent(dstSubresource.mipLevel);
VkRenderingAttachmentInfo attachmentInfo = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO };
attachmentInfo.imageView = views->getDstView();
attachmentInfo.imageView = views.dstImageView->handle();
attachmentInfo.imageLayout = dstLayout;
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@ -4013,7 +3946,6 @@ namespace dxvk {
m_cmd->trackResource<DxvkAccess::Write>(dstImage);
m_cmd->trackResource<DxvkAccess::Read>(srcImage);
m_cmd->trackResource<DxvkAccess::None>(views);
}
@ -4530,7 +4462,7 @@ namespace dxvk {
VkExtent3D passExtent = dstImage->mipLevelExtent(region.dstSubresource.mipLevel);
Rc<DxvkMetaCopyViews> views = new DxvkMetaCopyViews(m_device->vkd(),
DxvkMetaCopyViews views(
dstImage, region.dstSubresource, dstFormat,
srcImage, region.srcSubresource, srcFormat);
@ -4541,10 +4473,15 @@ namespace dxvk {
VkDescriptorSet descriptorSet = m_descriptorPool->alloc(pipeInfo.dsetLayout);
std::array<VkDescriptorImageInfo, 2> descriptorImages = {{
{ VK_NULL_HANDLE, views->getSrcView(), srcLayout },
{ VK_NULL_HANDLE, views->getSrcStencilView(), srcLayout },
{ VK_NULL_HANDLE, views.srcImageView->handle(), srcLayout },
{ VK_NULL_HANDLE, VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED },
}};
if (views.srcStencilView) {
descriptorImages[1].imageView = views.srcStencilView->handle();
descriptorImages[1].imageLayout = srcLayout;
}
std::array<VkWriteDescriptorSet, 2> descriptorWrites;
for (uint32_t i = 0; i < descriptorWrites.size(); i++) {
@ -4574,7 +4511,7 @@ namespace dxvk {
scissor.extent = { region.extent.width, region.extent.height };
VkRenderingAttachmentInfo attachmentInfo = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO };
attachmentInfo.imageView = views->getDstView();
attachmentInfo.imageView = views.dstImageView->handle();
attachmentInfo.imageLayout = dstLayout;
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@ -4632,7 +4569,6 @@ namespace dxvk {
m_cmd->trackResource<DxvkAccess::Write>(dstImage);
m_cmd->trackResource<DxvkAccess::Read>(srcImage);
m_cmd->trackResource<DxvkAccess::None>(views);
}

View File

@ -1526,17 +1526,6 @@ namespace dxvk {
VkImageSubresourceLayers srcSubresource,
VkOffset3D srcOffset,
VkExtent3D extent);
void copyImageFbDirect(
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
VkOffset3D dstOffset,
VkFormat dstFormat,
const Rc<DxvkImage>& srcImage,
VkImageSubresourceLayers srcSubresource,
VkOffset3D srcOffset,
VkFormat srcFormat,
VkExtent3D extent);
bool copyImageClear(
const Rc<DxvkImage>& dstImage,

View File

@ -16,63 +16,57 @@
namespace dxvk {
DxvkMetaCopyViews::DxvkMetaCopyViews(
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkImage>& dstImage,
const VkImageSubresourceLayers& dstSubresources,
VkFormat dstFormat,
const Rc<DxvkImage>& srcImage,
const VkImageSubresourceLayers& srcSubresources,
VkFormat srcFormat)
: m_vkd(vkd) {
VkFormat srcFormat) {
VkImageAspectFlags dstAspects = dstImage->formatInfo()->aspectMask;
VkImageAspectFlags srcAspects = srcImage->formatInfo()->aspectMask;
// We don't support 3D here, so we can safely ignore that case
m_dstViewType = dstImage->info().type == VK_IMAGE_TYPE_1D
VkImageViewType dstViewType = dstImage->info().type == VK_IMAGE_TYPE_1D
? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
m_srcViewType = srcImage->info().type == VK_IMAGE_TYPE_1D
VkImageViewType srcViewType = srcImage->info().type == VK_IMAGE_TYPE_1D
? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO };
usageInfo.usage = (dstAspects & VK_IMAGE_ASPECT_COLOR_BIT)
? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
DxvkImageViewKey dstViewInfo;
dstViewInfo.viewType = dstViewType;
dstViewInfo.format = dstFormat;
dstViewInfo.aspects = dstSubresources.aspectMask;
dstViewInfo.mipIndex = dstSubresources.mipLevel;
dstViewInfo.mipCount = 1u;
dstViewInfo.layerIndex = dstSubresources.baseArrayLayer;
dstViewInfo.layerCount = dstSubresources.layerCount;
dstViewInfo.usage = (dstAspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
// Create destination view
VkImageViewCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &usageInfo };
info.image = dstImage->handle();
info.viewType = m_dstViewType;
info.format = dstFormat;
info.subresourceRange = vk::makeSubresourceRange(dstSubresources);
if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_dstImageView)))
throw DxvkError("DxvkMetaCopyViews: Failed to create destination image view");
dstImageView = dstImage->createView(dstViewInfo);
// Create source image views
usageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
DxvkImageViewKey srcViewInfo;
srcViewInfo.viewType = srcViewType;
srcViewInfo.format = srcFormat;
srcViewInfo.aspects = srcSubresources.aspectMask & ~VK_IMAGE_ASPECT_STENCIL_BIT;
srcViewInfo.mipIndex = srcSubresources.mipLevel;
srcViewInfo.mipCount = 1u;
srcViewInfo.layerIndex = srcSubresources.baseArrayLayer;
srcViewInfo.layerCount = srcSubresources.layerCount;
srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
info.image = srcImage->handle();
info.viewType = m_srcViewType;
info.format = srcFormat;
info.subresourceRange = vk::makeSubresourceRange(srcSubresources);
info.subresourceRange.aspectMask = srcAspects & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_srcImageView)))
throw DxvkError("DxvkMetaCopyViews: Failed to create source image view");
srcImageView = srcImage->createView(srcViewInfo);
if (srcAspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_srcStencilView)))
throw DxvkError("DxvkMetaCopyViews: Failed to create source stencil view");
srcViewInfo.aspects = VK_IMAGE_ASPECT_STENCIL_BIT;
srcStencilView = srcImage->createView(srcViewInfo);
}
}
DxvkMetaCopyViews::~DxvkMetaCopyViews() {
m_vkd->vkDestroyImageView(m_vkd->device(), m_dstImageView, nullptr);
m_vkd->vkDestroyImageView(m_vkd->device(), m_srcImageView, nullptr);
m_vkd->vkDestroyImageView(m_vkd->device(), m_srcStencilView, nullptr);
}

View File

@ -75,12 +75,11 @@ namespace dxvk {
* Creates and manages views used in a
* framebuffer-based copy operations.
*/
class DxvkMetaCopyViews : public DxvkResource {
class DxvkMetaCopyViews {
public:
DxvkMetaCopyViews(
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkImage>& dstImage,
const VkImageSubresourceLayers& dstSubresources,
VkFormat dstFormat,
@ -90,24 +89,9 @@ namespace dxvk {
~DxvkMetaCopyViews();
VkImageView getDstView() const { return m_dstImageView; }
VkImageView getSrcView() const { return m_srcImageView; }
VkImageView getSrcStencilView() const { return m_srcStencilView; }
VkImageViewType getSrcViewType() const {
return m_srcViewType;
}
private:
Rc<vk::DeviceFn> m_vkd;
VkImageViewType m_srcViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
VkImageViewType m_dstViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
VkImageView m_dstImageView = VK_NULL_HANDLE;
VkImageView m_srcImageView = VK_NULL_HANDLE;
VkImageView m_srcStencilView = VK_NULL_HANDLE;
Rc<DxvkImageView> dstImageView;
Rc<DxvkImageView> srcImageView;
Rc<DxvkImageView> srcStencilView;
};