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

[dxvk] Clean up internal memory allocation API

This commit is contained in:
Philip Rebohle 2022-08-25 18:20:11 +02:00
parent 5117210c93
commit a2a21cb4d3
4 changed files with 165 additions and 136 deletions

View File

@ -65,25 +65,32 @@ namespace dxvk {
DxvkBufferHandle handle; DxvkBufferHandle handle;
if (vkd->vkCreateBuffer(vkd->device(), if (vkd->vkCreateBuffer(vkd->device(), &info, nullptr, &handle.buffer)) {
&info, nullptr, &handle.buffer) != VK_SUCCESS) {
throw DxvkError(str::format( throw DxvkError(str::format(
"DxvkBuffer: Failed to create buffer:" "DxvkBuffer: Failed to create buffer:"
"\n size: ", info.size, "\n size: ", info.size,
"\n usage: ", info.usage)); "\n usage: ", info.usage));
} }
VkMemoryDedicatedRequirements dedicatedRequirements = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS };
VkMemoryRequirements2 memReq = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicatedRequirements };
VkBufferMemoryRequirementsInfo2 memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 };
memReqInfo.buffer = handle.buffer;
VkMemoryDedicatedAllocateInfo dedMemoryAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO };
dedMemoryAllocInfo.buffer = handle.buffer;
vkd->vkGetBufferMemoryRequirements2( // Query memory requirements and whether to use a dedicated allocation
vkd->device(), &memReqInfo, &memReq); DxvkMemoryRequirements memoryRequirements = { };
memoryRequirements.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS };
memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &memoryRequirements.dedicated };
VkBufferMemoryRequirementsInfo2 memoryRequirementInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 };
memoryRequirementInfo.buffer = handle.buffer;
vkd->vkGetBufferMemoryRequirements2(vkd->device(),
&memoryRequirementInfo, &memoryRequirements.core);
// Fill in desired memory properties
DxvkMemoryProperties memoryProperties = { };
memoryProperties.flags = m_memFlags;
if (memoryRequirements.dedicated.prefersDedicatedAllocation) {
memoryProperties.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO };
memoryProperties.dedicated.buffer = handle.buffer;
}
// Use high memory priority for GPU-writable resources // Use high memory priority for GPU-writable resources
bool isGpuWritable = (m_info.access & ( bool isGpuWritable = (m_info.access & (
@ -102,9 +109,7 @@ namespace dxvk {
&& (m_info.usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) && (m_info.usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT))
hints.set(DxvkMemoryFlag::Transient); hints.set(DxvkMemoryFlag::Transient);
// Ask driver whether we should be using a dedicated allocation handle.memory = m_memAlloc->alloc(memoryRequirements, memoryProperties, hints);
handle.memory = m_memAlloc->alloc(&memReq.memoryRequirements,
dedicatedRequirements, dedMemoryAllocInfo, m_memFlags, hints);
if (vkd->vkBindBufferMemory(vkd->device(), handle.buffer, if (vkd->vkBindBufferMemory(vkd->device(), handle.buffer,
handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS) handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS)

View File

@ -22,7 +22,10 @@ namespace dxvk {
VkImageFormatListCreateInfo formatList = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO }; VkImageFormatListCreateInfo formatList = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO };
formatList.viewFormatCount = createInfo.viewFormatCount; formatList.viewFormatCount = createInfo.viewFormatCount;
formatList.pViewFormats = createInfo.viewFormats; formatList.pViewFormats = createInfo.viewFormats;
VkExternalMemoryImageCreateInfo externalInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO };
externalInfo.handleTypes = createInfo.sharing.type;
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, &formatList }; VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, &formatList };
info.flags = createInfo.flags; info.flags = createInfo.flags;
info.imageType = createInfo.type; info.imageType = createInfo.type;
@ -36,17 +39,10 @@ namespace dxvk {
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.initialLayout = createInfo.initialLayout; info.initialLayout = createInfo.initialLayout;
m_shared = canShareImage(info, createInfo.sharing); if ((m_shared = canShareImage(info, createInfo.sharing)))
VkExternalMemoryImageCreateInfo externalInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO };
if (m_shared) {
externalInfo.pNext = std::exchange(info.pNext, &externalInfo); externalInfo.pNext = std::exchange(info.pNext, &externalInfo);
externalInfo.handleTypes = createInfo.sharing.type;
} if (m_vkd->vkCreateImage(m_vkd->device(), &info, nullptr, &m_image.image)) {
if (m_vkd->vkCreateImage(m_vkd->device(),
&info, nullptr, &m_image.image) != VK_SUCCESS) {
throw DxvkError(str::format( throw DxvkError(str::format(
"DxvkImage: Failed to create image:", "DxvkImage: Failed to create image:",
"\n Type: ", info.imageType, "\n Type: ", info.imageType,
@ -61,40 +57,52 @@ namespace dxvk {
"\n Tiling: ", info.tiling)); "\n Tiling: ", info.tiling));
} }
// Get memory requirements for the image. We may enforce strict // Get memory requirements for the image and ask driver
// alignment on non-linear images in order not to violate the // whether we need to use a dedicated allocation.
// bufferImageGranularity limit, which may be greater than the DxvkMemoryRequirements memoryRequirements = { };
// required resource memory alignment on some GPUs. memoryRequirements.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS };
VkMemoryDedicatedRequirements dedicatedRequirements = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS }; memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &memoryRequirements.dedicated };
VkMemoryRequirements2 memReq = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicatedRequirements };
VkImageMemoryRequirementsInfo2 memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 };
memReqInfo.image = m_image.image;
VkMemoryDedicatedAllocateInfo dedMemoryAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO }; VkImageMemoryRequirementsInfo2 memoryRequirementInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 };
dedMemoryAllocInfo.image = m_image.image; memoryRequirementInfo.image = m_image.image;
VkExportMemoryAllocateInfo exportInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO }; m_vkd->vkGetImageMemoryRequirements2(m_vkd->device(),
if (m_shared && createInfo.sharing.mode == DxvkSharedHandleMode::Export) { &memoryRequirementInfo, &memoryRequirements.core);
exportInfo.pNext = std::exchange(dedMemoryAllocInfo.pNext, &exportInfo);
exportInfo.handleTypes = createInfo.sharing.type; // Fill in desired memory properties
DxvkMemoryProperties memoryProperties = { };
memoryProperties.flags = m_memFlags;
if (m_shared) {
memoryRequirements.dedicated.prefersDedicatedAllocation = VK_TRUE;
memoryRequirements.dedicated.requiresDedicatedAllocation = VK_TRUE;
if (createInfo.sharing.mode == DxvkSharedHandleMode::Export) {
memoryProperties.sharedExport = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO };
memoryProperties.sharedExport.handleTypes = createInfo.sharing.type;
}
if (createInfo.sharing.mode == DxvkSharedHandleMode::Import) {
memoryProperties.sharedImportWin32 = { VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR };
memoryProperties.sharedImportWin32.handleType = createInfo.sharing.type;
memoryProperties.sharedImportWin32.handle = createInfo.sharing.handle;
}
} }
#ifdef _WIN32 if (memoryRequirements.dedicated.prefersDedicatedAllocation) {
VkImportMemoryWin32HandleInfoKHR importInfo = { VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR }; memoryProperties.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO };
if (m_shared && createInfo.sharing.mode == DxvkSharedHandleMode::Import) { memoryProperties.dedicated.image = m_image.image;
importInfo.pNext = std::exchange(dedMemoryAllocInfo.pNext, &importInfo);
importInfo.handleType = createInfo.sharing.type;
importInfo.handle = createInfo.sharing.handle;
} }
#endif
m_vkd->vkGetImageMemoryRequirements2( // If there's a chance we won't create the image with a dedicated
m_vkd->device(), &memReqInfo, &memReq); // allocation, enforce strict alignment for tiled images to not
// violate the bufferImageGranularity requirement on some GPUs.
if (info.tiling != VK_IMAGE_TILING_LINEAR && !memoryRequirements.dedicated.requiresDedicatedAllocation) {
VkDeviceSize granularity = memAlloc.bufferImageGranularity();
if (info.tiling != VK_IMAGE_TILING_LINEAR && !dedicatedRequirements.prefersDedicatedAllocation) { auto& core = memoryRequirements.core.memoryRequirements;
memReq.memoryRequirements.size = align(memReq.memoryRequirements.size, memAlloc.bufferImageGranularity()); core.size = align(core.size, granularity);
memReq.memoryRequirements.alignment = align(memReq.memoryRequirements.alignment , memAlloc.bufferImageGranularity()); core.alignment = align(core.alignment, granularity);
} }
// Use high memory priority for GPU-writable resources // Use high memory priority for GPU-writable resources
@ -110,14 +118,7 @@ namespace dxvk {
if (isGpuWritable) if (isGpuWritable)
hints.set(DxvkMemoryFlag::GpuWritable); hints.set(DxvkMemoryFlag::GpuWritable);
if (m_shared) { m_image.memory = memAlloc.alloc(memoryRequirements, memoryProperties, hints);
dedicatedRequirements.prefersDedicatedAllocation = VK_TRUE;
dedicatedRequirements.requiresDedicatedAllocation = VK_TRUE;
}
// Ask driver whether we should be using a dedicated allocation
m_image.memory = memAlloc.alloc(&memReq.memoryRequirements,
dedicatedRequirements, dedMemoryAllocInfo, memFlags, hints);
// Try to bind the allocated memory slice to the image // Try to bind the allocated memory slice to the image
if (m_vkd->vkBindImageMemory(m_vkd->device(), m_image.image, if (m_vkd->vkBindImageMemory(m_vkd->device(), m_image.image,

View File

@ -211,63 +211,66 @@ namespace dxvk {
DxvkMemory DxvkMemoryAllocator::alloc( DxvkMemory DxvkMemoryAllocator::alloc(
const VkMemoryRequirements* req, const DxvkMemoryRequirements& req,
const VkMemoryDedicatedRequirements& dedAllocReq, DxvkMemoryProperties info,
const VkMemoryDedicatedAllocateInfo& dedAllocInfo,
VkMemoryPropertyFlags flags,
DxvkMemoryFlags hints) { DxvkMemoryFlags hints) {
std::lock_guard<dxvk::mutex> lock(m_mutex); std::lock_guard<dxvk::mutex> lock(m_mutex);
// Keep small allocations together to avoid fragmenting // Keep small allocations together to avoid fragmenting
// chunks for larger resources with lots of small gaps, // chunks for larger resources with lots of small gaps,
// as well as resources with potentially weird lifetimes // as well as resources with potentially weird lifetimes
if (req->size <= SmallAllocationThreshold) { if (req.core.memoryRequirements.size <= SmallAllocationThreshold) {
hints.set(DxvkMemoryFlag::Small); hints.set(DxvkMemoryFlag::Small);
hints.clr(DxvkMemoryFlag::GpuWritable, DxvkMemoryFlag::GpuReadable); hints.clr(DxvkMemoryFlag::GpuWritable, DxvkMemoryFlag::GpuReadable);
} }
// Ignore most hints for host-visible allocations since they // Ignore most hints for host-visible allocations since they
// usually don't make much sense for those resources // usually don't make much sense for those resources
if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) if (info.flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
hints = hints & DxvkMemoryFlag::Transient; hints = hints & DxvkMemoryFlag::Transient;
// Try to allocate from a memory type which supports the given flags exactly // Try to allocate from a memory type which supports the given flags exactly
auto dedAllocPtr = dedAllocReq.prefersDedicatedAllocation ? &dedAllocInfo : nullptr; DxvkMemory result = this->tryAlloc(req, info, hints);
DxvkMemory result = this->tryAlloc(req, dedAllocPtr, flags, hints);
// If the first attempt failed, try ignoring the dedicated allocation if (!result && !req.dedicated.requiresDedicatedAllocation) {
if (!result && dedAllocPtr && !dedAllocReq.requiresDedicatedAllocation) { // If that failed, try without a dedicated allocation
result = this->tryAlloc(req, nullptr, flags, hints); if (info.dedicated.image || info.dedicated.buffer) {
dedAllocPtr = nullptr; info.dedicated.image = VK_NULL_HANDLE;
info.dedicated.buffer = VK_NULL_HANDLE;
result = this->tryAlloc(req, info, hints);
}
} }
// Retry without the hint constraints
if (!result) { if (!result) {
// Retry without the hint constraints
hints.set(DxvkMemoryFlag::IgnoreConstraints); hints.set(DxvkMemoryFlag::IgnoreConstraints);
result = this->tryAlloc(req, nullptr, flags, hints); result = this->tryAlloc(req, info, hints);
} }
// If that still didn't work, probe slower memory types as well if (!result) {
VkMemoryPropertyFlags optFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT // If that still didn't work, probe slower memory types as well
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT; VkMemoryPropertyFlags optFlags = info.flags & (
VkMemoryPropertyFlags remFlags = 0; VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
while (!result && (flags & optFlags)) {
remFlags |= optFlags & -optFlags;
optFlags &= ~remFlags;
result = this->tryAlloc(req, dedAllocPtr, flags & ~remFlags, hints); while (!result && optFlags) {
VkMemoryPropertyFlags bit = optFlags & -optFlags;
optFlags &= ~bit;
info.flags &= ~bit;
result = this->tryAlloc(req, info, hints);
}
} }
if (!result) { if (!result) {
DxvkAdapterMemoryInfo memHeapInfo = m_device->adapter()->getMemoryHeapInfo(); DxvkAdapterMemoryInfo memHeapInfo = m_device->adapter()->getMemoryHeapInfo();
Logger::err(str::format( Logger::err(str::format(
"DxvkMemoryAllocator: Memory allocation failed", "DxvkMemoryAllocator: Memory allocation failed",
"\n Size: ", req->size, "\n Size: ", req.core.memoryRequirements.size,
"\n Alignment: ", req->alignment, "\n Alignment: ", req.core.memoryRequirements.alignment,
"\n Mem flags: ", "0x", std::hex, flags, "\n Mem types: ", "0x", std::hex, req.core.memoryRequirements.memoryTypeBits));
"\n Mem types: ", "0x", std::hex, req->memoryTypeBits));
for (uint32_t i = 0; i < m_memProps.memoryHeapCount; i++) { for (uint32_t i = 0; i < m_memProps.memoryHeapCount; i++) {
Logger::err(str::format("Heap ", i, ": ", Logger::err(str::format("Heap ", i, ": ",
@ -290,19 +293,20 @@ namespace dxvk {
DxvkMemory DxvkMemoryAllocator::tryAlloc( DxvkMemory DxvkMemoryAllocator::tryAlloc(
const VkMemoryRequirements* req, const DxvkMemoryRequirements& req,
const VkMemoryDedicatedAllocateInfo* dedAllocInfo, const DxvkMemoryProperties& info,
VkMemoryPropertyFlags flags,
DxvkMemoryFlags hints) { DxvkMemoryFlags hints) {
DxvkMemory result; DxvkMemory result;
for (uint32_t i = 0; i < m_memProps.memoryTypeCount && !result; i++) { for (uint32_t i = 0; i < m_memProps.memoryTypeCount && !result; i++) {
const bool supported = (req->memoryTypeBits & (1u << i)) != 0; const bool supported = (req.core.memoryRequirements.memoryTypeBits & (1u << i)) != 0;
const bool adequate = (m_memTypes[i].memType.propertyFlags & flags) == flags; const bool adequate = (m_memTypes[i].memType.propertyFlags & info.flags) == info.flags;
if (supported && adequate) { if (supported && adequate) {
result = this->tryAllocFromType(&m_memTypes[i], result = this->tryAllocFromType(&m_memTypes[i],
flags, req->size, req->alignment, hints, dedAllocInfo); req.core.memoryRequirements.size,
req.core.memoryRequirements.alignment,
info, hints);
} }
} }
@ -312,27 +316,25 @@ namespace dxvk {
DxvkMemory DxvkMemoryAllocator::tryAllocFromType( DxvkMemory DxvkMemoryAllocator::tryAllocFromType(
DxvkMemoryType* type, DxvkMemoryType* type,
VkMemoryPropertyFlags flags,
VkDeviceSize size, VkDeviceSize size,
VkDeviceSize align, VkDeviceSize align,
DxvkMemoryFlags hints, const DxvkMemoryProperties& info,
const VkMemoryDedicatedAllocateInfo* dedAllocInfo) { DxvkMemoryFlags hints) {
VkDeviceSize chunkSize = pickChunkSize(type->memTypeId, hints); VkDeviceSize chunkSize = pickChunkSize(type->memTypeId, hints);
DxvkMemory memory; DxvkMemory memory;
if (size >= chunkSize || dedAllocInfo) { if (size >= chunkSize || info.dedicated.buffer || info.dedicated.image) {
if (this->shouldFreeEmptyChunks(type->heap, size)) if (this->shouldFreeEmptyChunks(type->heap, size))
this->freeEmptyChunks(type->heap); this->freeEmptyChunks(type->heap);
DxvkDeviceMemory devMem = this->tryAllocDeviceMemory( DxvkDeviceMemory devMem = this->tryAllocDeviceMemory(type, size, info, hints);
type, flags, size, hints, dedAllocInfo);
if (devMem.memHandle != VK_NULL_HANDLE) if (devMem.memHandle != VK_NULL_HANDLE)
memory = DxvkMemory(this, nullptr, type, devMem.memHandle, 0, size, devMem.memPointer); memory = DxvkMemory(this, nullptr, type, devMem.memHandle, 0, size, devMem.memPointer);
} else { } else {
for (uint32_t i = 0; i < type->chunks.size() && !memory; i++) for (uint32_t i = 0; i < type->chunks.size() && !memory; i++)
memory = type->chunks[i]->alloc(flags, size, align, hints); memory = type->chunks[i]->alloc(info.flags, size, align, hints);
if (!memory) { if (!memory) {
DxvkDeviceMemory devMem; DxvkDeviceMemory devMem;
@ -341,11 +343,11 @@ namespace dxvk {
this->freeEmptyChunks(type->heap); this->freeEmptyChunks(type->heap);
for (uint32_t i = 0; i < 6 && (chunkSize >> i) >= size && !devMem.memHandle; i++) for (uint32_t i = 0; i < 6 && (chunkSize >> i) >= size && !devMem.memHandle; i++)
devMem = tryAllocDeviceMemory(type, flags, chunkSize >> i, hints, nullptr); devMem = tryAllocDeviceMemory(type, chunkSize >> i, info, hints);
if (devMem.memHandle) { if (devMem.memHandle) {
Rc<DxvkMemoryChunk> chunk = new DxvkMemoryChunk(this, type, devMem, hints); Rc<DxvkMemoryChunk> chunk = new DxvkMemoryChunk(this, type, devMem, hints);
memory = chunk->alloc(flags, size, align, hints); memory = chunk->alloc(info.flags, size, align, hints);
type->chunks.push_back(std::move(chunk)); type->chunks.push_back(std::move(chunk));
} }
@ -361,11 +363,10 @@ namespace dxvk {
DxvkDeviceMemory DxvkMemoryAllocator::tryAllocDeviceMemory( DxvkDeviceMemory DxvkMemoryAllocator::tryAllocDeviceMemory(
DxvkMemoryType* type, DxvkMemoryType* type,
VkMemoryPropertyFlags flags,
VkDeviceSize size, VkDeviceSize size,
DxvkMemoryFlags hints, DxvkMemoryProperties info,
const VkMemoryDedicatedAllocateInfo* dedAllocInfo) { DxvkMemoryFlags hints) {
bool useMemoryPriority = (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) bool useMemoryPriority = (info.flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
&& (m_device->features().extMemoryPriority.memoryPriority); && (m_device->features().extMemoryPriority.memoryPriority);
if (type->heap->budget && type->heap->stats.memoryAllocated + size > type->heap->budget) if (type->heap->budget && type->heap->stats.memoryAllocated + size > type->heap->budget)
@ -380,23 +381,32 @@ namespace dxvk {
DxvkDeviceMemory result; DxvkDeviceMemory result;
result.memSize = size; result.memSize = size;
result.memFlags = flags; result.memFlags = info.flags;
result.priority = priority; result.priority = priority;
VkMemoryPriorityAllocateInfoEXT prio = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT }; VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT };
prio.priority = priority; priorityInfo.priority = priority;
VkMemoryAllocateInfo info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, dedAllocInfo }; VkMemoryAllocateInfo memoryInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
info.allocationSize = size; memoryInfo.allocationSize = size;
info.memoryTypeIndex = type->memTypeId; memoryInfo.memoryTypeIndex = type->memTypeId;
if (info.sharedExport.handleTypes)
info.sharedExport.pNext = std::exchange(memoryInfo.pNext, &info.sharedExport);
if (info.sharedImportWin32.handleType)
info.sharedImportWin32.pNext = std::exchange(memoryInfo.pNext, &info.sharedImportWin32);
if (info.dedicated.buffer || info.dedicated.image)
info.dedicated.pNext = std::exchange(memoryInfo.pNext, &info.dedicated);
if (useMemoryPriority) if (useMemoryPriority)
prio.pNext = std::exchange(info.pNext, &prio); priorityInfo.pNext = std::exchange(memoryInfo.pNext, &priorityInfo);
if (m_vkd->vkAllocateMemory(m_vkd->device(), &info, nullptr, &result.memHandle) != VK_SUCCESS) if (m_vkd->vkAllocateMemory(m_vkd->device(), &memoryInfo, nullptr, &result.memHandle) != VK_SUCCESS)
return DxvkDeviceMemory(); return DxvkDeviceMemory();
if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { if (info.flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
VkResult status = m_vkd->vkMapMemory(m_vkd->device(), result.memHandle, 0, VK_WHOLE_SIZE, 0, &result.memPointer); VkResult status = m_vkd->vkMapMemory(m_vkd->device(), result.memHandle, 0, VK_WHOLE_SIZE, 0, &result.memPointer);
if (status != VK_SUCCESS) { if (status != VK_SUCCESS) {

View File

@ -271,8 +271,28 @@ namespace dxvk {
bool checkHints(DxvkMemoryFlags hints) const; bool checkHints(DxvkMemoryFlags hints) const;
}; };
/**
* \brief Memory requirement info
*/
struct DxvkMemoryRequirements {
VkMemoryDedicatedRequirements dedicated;
VkMemoryRequirements2 core;
};
/**
* \brief Memory allocation info
*/
struct DxvkMemoryProperties {
VkExportMemoryAllocateInfo sharedExport;
VkImportMemoryWin32HandleInfoKHR sharedImportWin32;
VkMemoryDedicatedAllocateInfo dedicated;
VkMemoryPropertyFlags flags;
};
/** /**
* \brief Memory allocator * \brief Memory allocator
* *
@ -305,17 +325,13 @@ namespace dxvk {
* \brief Allocates device memory * \brief Allocates device memory
* *
* \param [in] req Memory requirements * \param [in] req Memory requirements
* \param [in] dedAllocReq Dedicated allocation requirements * \param [in] info Memory properties
* \param [in] dedAllocInfo Dedicated allocation info
* \param [in] flags Memory type flags
* \param [in] hints Memory hints * \param [in] hints Memory hints
* \returns Allocated memory slice * \returns Allocated memory slice
*/ */
DxvkMemory alloc( DxvkMemory alloc(
const VkMemoryRequirements* req, const DxvkMemoryRequirements& req,
const VkMemoryDedicatedRequirements& dedAllocReq, DxvkMemoryProperties info,
const VkMemoryDedicatedAllocateInfo& dedAllocInfo,
VkMemoryPropertyFlags flags,
DxvkMemoryFlags hints); DxvkMemoryFlags hints);
/** /**
@ -342,25 +358,22 @@ namespace dxvk {
std::array<DxvkMemoryType, VK_MAX_MEMORY_TYPES> m_memTypes; std::array<DxvkMemoryType, VK_MAX_MEMORY_TYPES> m_memTypes;
DxvkMemory tryAlloc( DxvkMemory tryAlloc(
const VkMemoryRequirements* req, const DxvkMemoryRequirements& req,
const VkMemoryDedicatedAllocateInfo* dedAllocInfo, const DxvkMemoryProperties& info,
VkMemoryPropertyFlags flags,
DxvkMemoryFlags hints); DxvkMemoryFlags hints);
DxvkMemory tryAllocFromType( DxvkMemory tryAllocFromType(
DxvkMemoryType* type, DxvkMemoryType* type,
VkMemoryPropertyFlags flags,
VkDeviceSize size, VkDeviceSize size,
VkDeviceSize align, VkDeviceSize align,
DxvkMemoryFlags hints, const DxvkMemoryProperties& info,
const VkMemoryDedicatedAllocateInfo* dedAllocInfo); DxvkMemoryFlags hints);
DxvkDeviceMemory tryAllocDeviceMemory( DxvkDeviceMemory tryAllocDeviceMemory(
DxvkMemoryType* type, DxvkMemoryType* type,
VkMemoryPropertyFlags flags,
VkDeviceSize size, VkDeviceSize size,
DxvkMemoryFlags hints, DxvkMemoryProperties info,
const VkMemoryDedicatedAllocateInfo* dedAllocInfo); DxvkMemoryFlags hints);
void free( void free(
const DxvkMemory& memory); const DxvkMemory& memory);