mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22:29:15 +01:00
[dxvk] Implement image swapping
This commit is contained in:
parent
5193e8ef24
commit
41a91cbae6
@ -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,
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
@ -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,
|
||||||
@ -205,6 +227,16 @@ namespace dxvk {
|
|||||||
throw DxvkError(str::format("DxvkImageView: Invalid view type: ", m_info.type));
|
throw DxvkError(str::format("DxvkImageView: Invalid view type: ", m_info.type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
@ -261,5 +293,22 @@ namespace dxvk {
|
|||||||
"\n Tiling: ", m_image->info().tiling));
|
"\n Tiling: ", m_image->info().tiling));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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:
|
||||||
|
|
||||||
@ -283,6 +285,16 @@ namespace dxvk {
|
|||||||
VkDeviceSize memSize() const {
|
VkDeviceSize memSize() const {
|
||||||
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:
|
||||||
|
|
||||||
@ -298,6 +310,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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -481,7 +495,32 @@ namespace dxvk {
|
|||||||
void createViews();
|
void createViews();
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user