Fixes after merge for VK_KHR_external_memory_win32 support

This commit is contained in:
Adam Sawicki 2024-08-28 11:43:13 +02:00
parent 0d55cf5276
commit ca17831d74
4 changed files with 92 additions and 55 deletions

View File

@ -6273,11 +6273,17 @@ private:
uint32_t m_MapCount;
void* m_pMappedData;
VmaWin32Handle m_Handle; // Win32 handle
VmaWin32Handle m_Handle;
};
#endif // _VMA_DEVICE_MEMORY_BLOCK
#ifndef _VMA_ALLOCATION_T
struct VmaAllocationExtraData
{
void* m_pMappedData = VMA_NULL; // Not null means memory is mapped.
VmaWin32Handle m_Handle;
};
struct VmaAllocation_T
{
friend struct VmaDedicatedAllocationListItemTraits;
@ -6310,12 +6316,14 @@ public:
bool mapped);
// pMappedData not null means allocation is created with MAPPED flag.
void InitDedicatedAllocation(
VmaAllocator allocator,
VmaPool hParentPool,
uint32_t memoryTypeIndex,
VkDeviceMemory hMemory,
VmaSuballocationType suballocationType,
void* pMappedData,
VkDeviceSize size);
void Destroy(VmaAllocator allocator);
ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
VkDeviceSize GetAlignment() const { return m_Alignment; }
@ -6375,10 +6383,9 @@ private:
{
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
VkDeviceMemory m_hMemory;
void* m_pMappedData; // Not null means memory is mapped.
VmaAllocationExtraData* m_ExtraData;
VmaAllocation_T* m_Prev;
VmaAllocation_T* m_Next;
VmaWin32Handle m_Handle; // Win32 handle
};
union
{
@ -6401,6 +6408,8 @@ private:
#if VMA_STATS_STRING_ENABLED
VmaBufferImageUsage m_BufferImageUsage; // 0 if unknown.
#endif
void EnsureExtraData(VmaAllocator hAllocator);
};
#endif // _VMA_ALLOCATION_T
@ -10867,6 +10876,7 @@ void VmaAllocation_T::InitBlockAllocation(
}
void VmaAllocation_T::InitDedicatedAllocation(
VmaAllocator allocator,
VmaPool hParentPool,
uint32_t memoryTypeIndex,
VkDeviceMemory hMemory,
@ -10881,16 +10891,29 @@ void VmaAllocation_T::InitDedicatedAllocation(
m_Size = size;
m_MemoryTypeIndex = memoryTypeIndex;
m_SuballocationType = (uint8_t)suballocationType;
if(pMappedData != VMA_NULL)
m_DedicatedAllocation.m_ExtraData = VMA_NULL;
m_DedicatedAllocation.m_hParentPool = hParentPool;
m_DedicatedAllocation.m_hMemory = hMemory;
m_DedicatedAllocation.m_Prev = VMA_NULL;
m_DedicatedAllocation.m_Next = VMA_NULL;
if (pMappedData != VMA_NULL)
{
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;
EnsureExtraData(allocator);
m_DedicatedAllocation.m_ExtraData->m_pMappedData = pMappedData;
}
}
void VmaAllocation_T::Destroy(VmaAllocator allocator)
{
FreeName(allocator);
if (GetType() == ALLOCATION_TYPE_DEDICATED)
{
vma_delete(allocator, m_DedicatedAllocation.m_ExtraData);
}
m_DedicatedAllocation.m_hParentPool = hParentPool;
m_DedicatedAllocation.m_hMemory = hMemory;
m_DedicatedAllocation.m_pMappedData = pMappedData;
m_DedicatedAllocation.m_Prev = VMA_NULL;
m_DedicatedAllocation.m_Next = VMA_NULL;
}
void VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName)
@ -10995,8 +11018,9 @@ void* VmaAllocation_T::GetMappedData() const
}
break;
case ALLOCATION_TYPE_DEDICATED:
VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0 || IsPersistentMap()));
return m_DedicatedAllocation.m_pMappedData;
VMA_ASSERT((m_DedicatedAllocation.m_ExtraData != VMA_NULL && m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL) ==
(m_MapCount != 0 || IsPersistentMap()));
return m_DedicatedAllocation.m_ExtraData != VMA_NULL ? m_DedicatedAllocation.m_ExtraData->m_pMappedData : VMA_NULL;
default:
VMA_ASSERT(0);
return VMA_NULL;
@ -11037,12 +11061,14 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
EnsureExtraData(hAllocator);
if (m_MapCount != 0 || IsPersistentMap())
{
if (m_MapCount < 0xFF)
{
VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
*ppData = m_DedicatedAllocation.m_pMappedData;
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL);
*ppData = m_DedicatedAllocation.m_ExtraData->m_pMappedData;
++m_MapCount;
return VK_SUCCESS;
}
@ -11063,7 +11089,7 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
ppData);
if (result == VK_SUCCESS)
{
m_DedicatedAllocation.m_pMappedData = *ppData;
m_DedicatedAllocation.m_ExtraData->m_pMappedData = *ppData;
m_MapCount = 1;
}
return result;
@ -11079,7 +11105,8 @@ void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
--m_MapCount;
if (m_MapCount == 0 && !IsPersistentMap())
{
m_DedicatedAllocation.m_pMappedData = VMA_NULL;
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData != VMA_NULL);
m_DedicatedAllocation.m_ExtraData->m_pMappedData = VMA_NULL;
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
hAllocator->m_hDevice,
m_DedicatedAllocation.m_hMemory);
@ -11118,14 +11145,14 @@ void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
#if VMA_EXTERNAL_MEMORY_WIN32
VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
{
// Where do we get this function from?
auto pvkGetMemoryWin32HandleKHR = hAllocator->GetVulkanFunctions().vkGetMemoryWin32HandleKHR;
switch (m_Type)
{
case ALLOCATION_TYPE_BLOCK:
return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle);
case ALLOCATION_TYPE_DEDICATED:
return m_DedicatedAllocation.m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
EnsureExtraData(hAllocator);
return m_DedicatedAllocation.m_ExtraData->m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
default:
VMA_ASSERT(0);
return VK_ERROR_FEATURE_NOT_PRESENT;
@ -11134,6 +11161,14 @@ VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTarget
#endif // VMA_EXTERNAL_MEMORY_WIN32
#endif // VMA_STATS_STRING_ENABLED
void VmaAllocation_T::EnsureExtraData(VmaAllocator hAllocator)
{
if (m_DedicatedAllocation.m_ExtraData == VMA_NULL)
{
m_DedicatedAllocation.m_ExtraData = vma_new(hAllocator, VmaAllocationExtraData)();
}
}
void VmaAllocation_T::FreeName(VmaAllocator hAllocator)
{
if(m_pName)
@ -11562,6 +11597,7 @@ void VmaBlockVector::Free(const VmaAllocation hAllocation)
}
m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
hAllocation->Destroy(m_hAllocator);
m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
}
@ -13705,7 +13741,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
}
*pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed);
(*pAllocation)->InitDedicatedAllocation(pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
(*pAllocation)->InitDedicatedAllocation(this, pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
if (isUserDataString)
(*pAllocation)->SetName(this, (const char*)pUserData);
else
@ -14041,8 +14077,6 @@ void VmaAllocator_T::FreeMemory(
FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
}
allocation->FreeName(this);
switch(allocation->GetType())
{
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
@ -14726,6 +14760,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
allocation->Destroy(this);
m_AllocationObjectAllocator.Free(allocation);
VMA_DEBUG_LOG_FORMAT(" Freed DedicatedMemory MemoryTypeIndex=%" PRIu32, memTypeIndex);
@ -16615,7 +16650,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock V
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32HandleKHR(VmaAllocator VMA_NOT_NULL allocator,
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle)
{
VMA_ASSERT(allocator && allocation);
VMA_ASSERT(allocator && allocation && pHandle);
VMA_DEBUG_GLOBAL_MUTEX_LOCK;
return allocation->GetWin32Handle(allocator, hTargetProcess, pHandle);
}
@ -16753,6 +16788,7 @@ VK_EXT_memory_budget | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT
VK_KHR_buffer_device_address | #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
VK_EXT_memory_priority | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT
VK_AMD_device_coherent_memory | #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
VK_KHR_external_memory_win32 | #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT
Example with fetching pointers to Vulkan functions dynamically:

View File

@ -34,7 +34,7 @@ foreach(SHADER ${SHADERS})
DEPENDS ${SHADER}
)
list(APPEND SPIRV_FILES ${SPIRV})
list(APPEND SPIRV_FILES ${SPIRV} ${SPIRV_BIN})
endforeach()
add_custom_target(VmaSampleShaders ALL DEPENDS ${SPIRV_FILES})

View File

@ -8258,61 +8258,59 @@ static void TestWin32Handles()
{
#if VMA_EXTERNAL_MEMORY_WIN32
wprintf(L"Test Win32 handles\n");
constexpr static VkExportMemoryAllocateInfoKHR exportInfo{
constexpr static VkExportMemoryAllocateInfoKHR exportMemAllocInfo{
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
};
constexpr static VkExternalMemoryBufferCreateInfoKHR externalInfo{
constexpr static VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo{
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
};
VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
sampleBufCreateInfo.size = 0x1000; // Doesn't matter.
sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
sampleBufCreateInfo.pNext = &externalInfo;
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufCreateInfo.size = 0x10000;
bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
bufCreateInfo.pNext = &externalMemBufCreateInfo;
VmaAllocationCreateInfo sampleAllocCreateInfo = {};
sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
sampleAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
uint32_t memTypeIndex;
uint32_t memTypeIndex = UINT32_MAX;
TEST(vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator,
&sampleBufCreateInfo, &sampleAllocCreateInfo, &memTypeIndex) == VK_SUCCESS);
// Check res...
&bufCreateInfo, &allocCreateInfo, &memTypeIndex) == VK_SUCCESS);
// Create a pool that can have at most 2 blocks, 128 MiB each.
VmaPoolCreateInfo poolCreateInfo = {};
poolCreateInfo.memoryTypeIndex = memTypeIndex;
poolCreateInfo.blockSize = 128ull * 1024 * 1024;
poolCreateInfo.maxBlockCount = 2;
poolCreateInfo.pMemoryAllocateNext = (void*)&exportInfo;
poolCreateInfo.pMemoryAllocateNext = (void*)&exportMemAllocInfo;
VmaPool pool;
VmaPool pool = VK_NULL_HANDLE;
TEST(vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool) == VK_SUCCESS);
allocCreateInfo.pool = pool;
sampleAllocCreateInfo.pool = pool;
for (size_t test = 0; test < 2; ++test)
{
if (test == 1)
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
VkBuffer buf;
VmaAllocation alloc;
VmaAllocationInfo allocInfo;
TEST(vmaCreateBuffer(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &buf, &alloc, &allocInfo) == VK_SUCCESS);
HANDLE handle;
HANDLE handle2;
TEST(vmaGetMemoryWin32HandleKHR(g_hAllocator, alloc, nullptr, &handle) == VK_SUCCESS);
TEST(handle != nullptr);
TEST(vmaGetMemoryWin32HandleKHR(g_hAllocator, alloc, nullptr, &handle2) == VK_SUCCESS);
TEST(handle2 != nullptr);
TEST(handle2 != handle);
VkBuffer buf = VK_NULL_HANDLE;
VmaAllocation alloc = VK_NULL_HANDLE;
TEST(vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr) == VK_SUCCESS);
HANDLE handle = NULL;
HANDLE handle2 = NULL;
TEST(vmaGetMemoryWin32HandleKHR(g_hAllocator, alloc, nullptr, &handle) == VK_SUCCESS);
TEST(handle != nullptr);
TEST(vmaGetMemoryWin32HandleKHR(g_hAllocator, alloc, nullptr, &handle2) == VK_SUCCESS);
TEST(handle2 != nullptr);
TEST(handle2 != handle);
vmaDestroyBuffer(g_hAllocator, buf, alloc);
TEST(CloseHandle(handle));
TEST(CloseHandle(handle2));
vmaDestroyBuffer(g_hAllocator, buf, alloc);
TEST(CloseHandle(handle));
TEST(CloseHandle(handle2));
}
vmaDestroyPool(g_hAllocator, pool);
#endif

View File

@ -96,6 +96,9 @@ include all public interface declarations. Example:
#pragma clang diagnostic ignored "-Wnullability-completeness"
#endif
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_win32.h>
#include "vk_mem_alloc.h"
#ifdef __clang__