[dxvk] Add shared handle access to DxvkImage memory.

Based off preliminary work from Josh.
This commit is contained in:
Derek Lesho 2022-02-23 15:56:31 -05:00 committed by Philip Rebohle
parent b5014401e7
commit 02d3e0d31f
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
6 changed files with 171 additions and 19 deletions

View File

@ -445,7 +445,7 @@ namespace dxvk {
VkImage imageHandle = m_presenter->getImage(i).image;
Rc<DxvkImage> image = new DxvkImage(
m_device->vkd(), imageInfo, imageHandle);
m_device.ptr(), imageInfo, imageHandle);
m_imageViews[i] = new DxvkImageView(
m_device->vkd(), image, viewInfo);
@ -662,4 +662,4 @@ namespace dxvk {
return str::format("D3D", apiVersion, " FL", flHi, "_", flLo);
}
}
}

View File

@ -997,7 +997,7 @@ namespace dxvk {
VkImage imageHandle = m_presenter->getImage(i).image;
Rc<DxvkImage> image = new DxvkImage(
m_device->vkd(), imageInfo, imageHandle);
m_device.ptr(), imageInfo, imageHandle);
m_imageViews[i] = new DxvkImageView(
m_device->vkd(), image, viewInfo);

View File

@ -135,14 +135,14 @@ namespace dxvk {
Rc<DxvkImage> DxvkDevice::createImage(
const DxvkImageCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {
return new DxvkImage(m_vkd, createInfo, m_objects.memoryManager(), memoryType);
return new DxvkImage(this, createInfo, m_objects.memoryManager(), memoryType);
}
Rc<DxvkImage> DxvkDevice::createImageFromVkImage(
const DxvkImageCreateInfo& createInfo,
VkImage image) {
return new DxvkImage(m_vkd, createInfo, image);
return new DxvkImage(this, createInfo, image);
}
Rc<DxvkImageView> DxvkDevice::createImageView(

View File

@ -1,16 +1,18 @@
#include "dxvk_image.h"
#include "dxvk_device.h"
namespace dxvk {
std::atomic<uint64_t> DxvkImageView::s_cookie = { 0ull };
DxvkImage::DxvkImage(
const Rc<vk::DeviceFn>& vkd,
const DxvkDevice* device,
const DxvkImageCreateInfo& createInfo,
DxvkMemoryAllocator& memAlloc,
VkMemoryPropertyFlags memFlags)
: m_vkd(vkd), m_info(createInfo), m_memFlags(memFlags) {
: m_vkd(device->vkd()), m_device(device), m_info(createInfo), m_memFlags(memFlags) {
// Copy the compatible view formats to a persistent array
m_viewFormats.resize(createInfo.viewFormatCount);
@ -42,6 +44,17 @@ namespace dxvk {
info.queueFamilyIndexCount = 0;
info.pQueueFamilyIndices = nullptr;
info.initialLayout = createInfo.initialLayout;
m_shared = canShareImage(info, createInfo.sharing);
VkExternalMemoryImageCreateInfo externalInfo;
if (m_shared) {
externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
externalInfo.pNext = nullptr;
externalInfo.handleTypes = createInfo.sharing.type;
formatList.pNext = &externalInfo;
}
if (m_vkd->vkCreateImage(m_vkd->device(),
&info, nullptr, &m_image.image) != VK_SUCCESS) {
@ -83,7 +96,29 @@ namespace dxvk {
dedMemoryAllocInfo.pNext = VK_NULL_HANDLE;
dedMemoryAllocInfo.buffer = VK_NULL_HANDLE;
dedMemoryAllocInfo.image = m_image.image;
VkExportMemoryAllocateInfo exportInfo;
if (m_shared && createInfo.sharing.mode == DxvkSharedHandleMode::Export) {
exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
exportInfo.pNext = nullptr;
exportInfo.handleTypes = createInfo.sharing.type;
dedMemoryAllocInfo.pNext = &exportInfo;
}
#ifdef _WIN32
VkImportMemoryWin32HandleInfoKHR importInfo;
if (m_shared && createInfo.sharing.mode == DxvkSharedHandleMode::Import) {
importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
importInfo.pNext = nullptr;
importInfo.handleType = createInfo.sharing.type;
importInfo.handle = createInfo.sharing.handle;
importInfo.name = nullptr;
dedMemoryAllocInfo.pNext = &importInfo;
}
#endif
m_vkd->vkGetImageMemoryRequirements2(
m_vkd->device(), &memReqInfo, &memReq);
@ -117,10 +152,10 @@ namespace dxvk {
DxvkImage::DxvkImage(
const Rc<vk::DeviceFn>& vkd,
const DxvkDevice* device,
const DxvkImageCreateInfo& info,
VkImage image)
: m_vkd(vkd), m_info(info), m_image({ image }) {
: m_vkd(device->vkd()), m_device(device), m_info(info), m_image({ image }) {
m_viewFormats.resize(info.viewFormatCount);
for (uint32_t i = 0; i < info.viewFormatCount; i++)
@ -135,8 +170,87 @@ namespace dxvk {
if (m_image.memory.memory() != VK_NULL_HANDLE)
m_vkd->vkDestroyImage(m_vkd->device(), m_image.image, nullptr);
}
bool DxvkImage::canShareImage(const VkImageCreateInfo& createInfo, const DxvkSharedHandleInfo& sharingInfo) const {
if (sharingInfo.mode == DxvkSharedHandleMode::None)
return false;
if (!m_device->extensions().khrExternalMemoryWin32) {
Logger::err("Failed to create shared resource: VK_KHR_EXTERNAL_MEMORY_WIN32 not supported");
return false;
}
VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
externalImageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
externalImageFormatInfo.pNext = VK_NULL_HANDLE;
externalImageFormatInfo.handleType = sharingInfo.type;
VkPhysicalDeviceImageFormatInfo2 imageFormatInfo;
imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
imageFormatInfo.pNext = &externalImageFormatInfo;
imageFormatInfo.format = createInfo.format;
imageFormatInfo.type = createInfo.imageType;
imageFormatInfo.tiling = createInfo.tiling;
imageFormatInfo.usage = createInfo.usage;
imageFormatInfo.flags = createInfo.flags;
VkExternalImageFormatProperties externalImageFormatProperties;
externalImageFormatProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;
externalImageFormatProperties.pNext = nullptr;
externalImageFormatProperties.externalMemoryProperties = {};
VkImageFormatProperties2 imageFormatProperties;
imageFormatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
imageFormatProperties.pNext = &externalImageFormatProperties;
imageFormatProperties.imageFormatProperties = {};
VkResult vr = m_device->adapter()->vki()->vkGetPhysicalDeviceImageFormatProperties2(
m_device->adapter()->handle(), &imageFormatInfo, &imageFormatProperties);
if (vr != VK_SUCCESS) {
Logger::err(str::format("Failed to create shared resource: getImageProperties failed:", vr));
return false;
}
if (sharingInfo.mode == DxvkSharedHandleMode::Export) {
bool ret = externalImageFormatProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
if (!ret)
Logger::err("Failed to create shared resource: image cannot be exported");
return ret;
}
if (sharingInfo.mode == DxvkSharedHandleMode::Import) {
bool ret = externalImageFormatProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
if (!ret)
Logger::err("Failed to create shared resource: image cannot be imported");
return ret;
}
return false;
}
HANDLE DxvkImage::sharedHandle() const {
HANDLE handle = INVALID_HANDLE_VALUE;
if (!m_shared)
return INVALID_HANDLE_VALUE;
#ifdef _WIN32
VkMemoryGetWin32HandleInfoKHR handleInfo;
handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
handleInfo.pNext = nullptr;
handleInfo.handleType = m_info.sharing.type;
handleInfo.memory = m_image.memory.memory();
if (m_vkd->vkGetMemoryWin32HandleKHR(m_vkd->device(), &handleInfo, &handle) != VK_SUCCESS)
Logger::warn("DxvkImage::DxvkImage: Failed to get shared handle for image");
#endif
return handle;
}
DxvkImageView::DxvkImageView(
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkImage>& image,
@ -247,4 +361,4 @@ namespace dxvk {
}
}
}
}

View File

@ -65,6 +65,9 @@ namespace dxvk {
// be used with this image
uint32_t viewFormatCount = 0;
const VkFormat* viewFormats = nullptr;
// Shared handle info
DxvkSharedHandleInfo sharing;
};
@ -124,7 +127,7 @@ namespace dxvk {
public:
DxvkImage(
const Rc<vk::DeviceFn>& vkd,
const DxvkDevice* device,
const DxvkImageCreateInfo& createInfo,
DxvkMemoryAllocator& memAlloc,
VkMemoryPropertyFlags memFlags);
@ -138,7 +141,7 @@ namespace dxvk {
* otherwise some image operations may fail.
*/
DxvkImage(
const Rc<vk::DeviceFn>& vkd,
const DxvkDevice* device,
const DxvkImageCreateInfo& info,
VkImage image);
@ -313,16 +316,26 @@ namespace dxvk {
result.layerCount = info().numLayers;
return result;
}
/**
* \brief Create a new shared handle to dedicated memory backing the image
* \returns The shared handle with the type given by DxvkSharedHandleInfo::type
*/
HANDLE sharedHandle() const;
private:
Rc<vk::DeviceFn> m_vkd;
const DxvkDevice* m_device;
DxvkImageCreateInfo m_info;
VkMemoryPropertyFlags m_memFlags;
DxvkPhysicalImage m_image;
bool m_shared = false;
small_vector<VkFormat, 4> m_viewFormats;
bool canShareImage(const VkImageCreateInfo& createInfo, const DxvkSharedHandleInfo& sharingInfo) const;
};
@ -555,4 +568,4 @@ namespace dxvk {
};
}
}

View File

@ -17,8 +17,33 @@ namespace dxvk {
VkDeviceSize memoryAllocated = 0;
VkDeviceSize memoryUsed = 0;
};
enum class DxvkSharedHandleMode {
None,
Import,
Export,
};
/**
* \brief Shared handle info
*
* The shared resource information for a given resource.
*/
struct DxvkSharedHandleInfo {
DxvkSharedHandleMode mode = DxvkSharedHandleMode::None;
VkExternalMemoryHandleTypeFlagBits type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
union {
#ifdef _WIN32
HANDLE handle = INVALID_HANDLE_VALUE;
#else
// Placeholder for other handle types, such as FD
void *dummy;
#endif
};
};
/**
* \brief Device memory object
*
@ -370,4 +395,4 @@ namespace dxvk {
};
}
}