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:
parent
ae90e74a5a
commit
2c176f4950
@ -3747,100 +3747,28 @@ 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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, ")"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1527,17 +1527,6 @@ namespace dxvk {
|
||||
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,
|
||||
VkImageSubresourceLayers dstSubresource,
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user