1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 07:29:17 +01:00

[dxvk] Implement image swapping

This commit is contained in:
Philip Rebohle 2020-01-08 17:15:53 +01:00 committed by Philip Rebohle
parent 5193e8ef24
commit 41a91cbae6
4 changed files with 127 additions and 0 deletions

View File

@ -1800,6 +1800,30 @@ namespace dxvk {
} }
void DxvkContext::swapImages(
const Rc<DxvkImage>& image1,
const Rc<DxvkImage>& image2) {
Rc<DxvkImageViewDump> dump = new DxvkImageViewDump(m_device->vkd());
image1->swap(image2, dump);
// Usage flags are required to be identical
VkImageUsageFlags usage = image1->info().usage;
if (usage & (VK_IMAGE_USAGE_SAMPLED_BIT
| VK_IMAGE_USAGE_STORAGE_BIT)) {
m_flags.set(
DxvkContextFlag::GpDirtyResources,
DxvkContextFlag::CpDirtyResources);
}
if (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
this->spillRenderPass();
m_cmd->trackResource<DxvkAccess::None>(dump);
}
void DxvkContext::transformImage( void DxvkContext::transformImage(
const Rc<DxvkImage>& dstImage, const Rc<DxvkImage>& dstImage,
const VkImageSubresourceRange& dstSubresources, const VkImageSubresourceRange& dstSubresources,

View File

@ -708,6 +708,21 @@ namespace dxvk {
VkResolveModeFlagBitsKHR depthMode, VkResolveModeFlagBitsKHR depthMode,
VkResolveModeFlagBitsKHR stencilMode); VkResolveModeFlagBitsKHR stencilMode);
/**
* \brief Swaps two images
*
* Exchanges the image handles and backing storage
* of the two images, and recreates all the views.
* Note that the two images must have been created
* with identical properties, including the memory
* properties.
* \param [in] image1 The first image
* \param [in] image2 The second image
*/
void swapImages(
const Rc<DxvkImage>& image1,
const Rc<DxvkImage>& image2);
/** /**
* \brief Transforms image subresource layouts * \brief Transforms image subresource layouts
* *

View File

@ -125,6 +125,20 @@ namespace dxvk {
} }
void DxvkImage::swap(const Rc<DxvkImage>& next, const Rc<DxvkImageViewDump>& dump) {
// Technically this could deadlock if two threads
// call this method, but that's undefined behaviour
// anyway so let's not care about it too much.
std::lock_guard lock1(this->m_viewLock);
std::lock_guard lock2(next->m_viewLock);
std::swap(this->m_image, next->m_image);
this->recreateViews(dump);
next->recreateViews(dump);
}
void DxvkImage::addView(DxvkImageView* view) { void DxvkImage::addView(DxvkImageView* view) {
m_viewList.push_back(view); m_viewList.push_back(view);
} }
@ -141,6 +155,14 @@ namespace dxvk {
} }
void DxvkImage::recreateViews(const Rc<DxvkImageViewDump>& dump) {
for (size_t i = 0; i < m_viewList.size(); i++) {
m_viewList[i]->discardViews(dump);
m_viewList[i]->createViews();
}
}
DxvkImageView::DxvkImageView( DxvkImageView::DxvkImageView(
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkImage>& image, const Rc<DxvkImage>& image,
@ -207,6 +229,16 @@ namespace dxvk {
} }
void DxvkImageView::discardViews(const Rc<DxvkImageViewDump>& dump) {
for (uint32_t i = 0; i < ViewCount; i++) {
if (m_views[i]) {
dump->addView(m_views[i]);
m_views[i] = VK_NULL_HANDLE;
}
}
}
void DxvkImageView::createView(VkImageViewType type, uint32_t numLayers) { void DxvkImageView::createView(VkImageViewType type, uint32_t numLayers) {
VkImageSubresourceRange subresourceRange; VkImageSubresourceRange subresourceRange;
subresourceRange.aspectMask = m_info.aspect; subresourceRange.aspectMask = m_info.aspect;
@ -262,4 +294,21 @@ namespace dxvk {
} }
} }
DxvkImageViewDump::DxvkImageViewDump(const Rc<vk::DeviceFn>& vkd)
: m_vkd(vkd) {
}
DxvkImageViewDump::~DxvkImageViewDump() {
for (auto view : m_views)
m_vkd->vkDestroyImageView(m_vkd->device(), view, nullptr);
}
void DxvkImageViewDump::addView(VkImageView view) {
m_views.push_back(view);
}
} }

View File

@ -9,6 +9,7 @@
namespace dxvk { namespace dxvk {
class DxvkImageView; class DxvkImageView;
class DxvkImageViewDump;
/** /**
* \brief Image create info * \brief Image create info
@ -115,6 +116,7 @@ namespace dxvk {
* memory type and if created with the linear tiling option. * memory type and if created with the linear tiling option.
*/ */
class DxvkImage : public DxvkResource { class DxvkImage : public DxvkResource {
friend class DxvkContext;
friend class DxvkImageView; friend class DxvkImageView;
public: public:
@ -284,6 +286,16 @@ namespace dxvk {
return m_image.memory.length(); return m_image.memory.length();
} }
/**
* \brief Swaps the image with another
*
* \param [in] next The other image
* \param [in] dump Image view dump
*/
void swap(
const Rc<DxvkImage>& next,
const Rc<DxvkImageViewDump>& dump);
private: private:
Rc<vk::DeviceFn> m_vkd; Rc<vk::DeviceFn> m_vkd;
@ -299,6 +311,8 @@ namespace dxvk {
void addView(DxvkImageView* view); void addView(DxvkImageView* view);
void removeView(DxvkImageView* view); void removeView(DxvkImageView* view);
void recreateViews(const Rc<DxvkImageViewDump>& dump);
}; };
@ -482,6 +496,31 @@ namespace dxvk {
void createView(VkImageViewType type, uint32_t numLayers); void createView(VkImageViewType type, uint32_t numLayers);
void discardViews(const Rc<DxvkImageViewDump>& dump);
};
/**
* \brief Image view dump
*
* Takes orphaned image view objects and destroys
* them when they are no longer needed.
*/
class DxvkImageViewDump : public DxvkResource {
public:
DxvkImageViewDump(const Rc<vk::DeviceFn>& vkd);
~DxvkImageViewDump();
void addView(VkImageView view);
private:
Rc<vk::DeviceFn> m_vkd;
std::vector<VkImageView> m_views;
}; };
} }