Skip to content

Commit 33bd6c6

Browse files
committed
made handle atomic
1 parent 746c651 commit 33bd6c6

1 file changed

Lines changed: 62 additions & 39 deletions

File tree

include/vk_mem_alloc.h

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6077,41 +6077,85 @@ class VmaWin32Handle
60776077
VmaWin32Handle(HANDLE hHandle) noexcept : m_hHandle(hHandle) { }
60786078
~VmaWin32Handle() noexcept { if (m_hHandle != VMA_NULL) { ::CloseHandle(m_hHandle); } }
60796079
VMA_CLASS_NO_COPY_NO_MOVE(VmaWin32Handle)
6080+
60806081
public:
6081-
VkResult Init(VkDevice device, VkDeviceMemory memory, decltype(&vkGetMemoryWin32HandleKHR) vkGetMemoryWin32HandleKHR) noexcept
6082+
// Strengthened
6083+
VkResult GetHandle(VkDevice device, VkDeviceMemory memory, decltype(&vkGetMemoryWin32HandleKHR) pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
6084+
{
6085+
*pHandle = VMA_NULL;
6086+
// We only care about atomicity of handle retrieval, not about memory order.
6087+
HANDLE handle = m_hHandle.load(std::memory_order_relaxed);
6088+
6089+
// Try to get handle first.
6090+
if (handle != VMA_NULL)
6091+
{
6092+
*pHandle = Duplicate(hTargetProcess);
6093+
return VK_SUCCESS;
6094+
}
6095+
6096+
HANDLE hCreatedHandle = VMA_NULL;
6097+
6098+
// If failed, try to create it.
6099+
VkResult res = Create(device, memory, pvkGetMemoryWin32HandleKHR, &hCreatedHandle);
6100+
if (res == VK_SUCCESS)
6101+
{
6102+
// Successfully created handle, try to set it.
6103+
if (!m_hHandle.compare_exchange_strong(handle, hCreatedHandle, std::memory_order_relaxed))
6104+
{
6105+
// AMD workaround
6106+
if (hCreatedHandle != m_hHandle.load(std::memory_order_relaxed))
6107+
{
6108+
::CloseHandle(hCreatedHandle);
6109+
}
6110+
}
6111+
}
6112+
6113+
// If somehow it was set in the meantime, return it.
6114+
if (m_hHandle.load(std::memory_order_relaxed))
6115+
{
6116+
*pHandle = Duplicate(hTargetProcess);
6117+
return VK_SUCCESS;
6118+
}
6119+
return res;
6120+
}
6121+
6122+
operator bool() const noexcept { return m_hHandle != VMA_NULL; }
6123+
private:
6124+
// Not atomic
6125+
static VkResult Create(VkDevice device, VkDeviceMemory memory, decltype(&vkGetMemoryWin32HandleKHR) pvkGetMemoryWin32HandleKHR, HANDLE* pHandle) noexcept
60826126
{
60836127
VkResult res = VK_ERROR_FEATURE_NOT_PRESENT;
6084-
if (vkGetMemoryWin32HandleKHR != VMA_NULL)
6128+
if (pvkGetMemoryWin32HandleKHR != VMA_NULL)
60856129
{
60866130
VkMemoryGetWin32HandleInfoKHR handleInfo{ };
60876131
handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
60886132
handleInfo.memory = memory;
60896133
handleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
6090-
res = vkGetMemoryWin32HandleKHR(device, &handleInfo, &m_hHandle);
6134+
res = pvkGetMemoryWin32HandleKHR(device, &handleInfo, pHandle);
60916135
}
60926136
return res;
60936137
}
60946138
HANDLE Duplicate(HANDLE hTargetProcess = VMA_NULL) const noexcept
60956139
{
6096-
if (!m_hHandle)
6097-
return m_hHandle;
6140+
HANDLE handle = m_hHandle.load(std::memory_order_relaxed);
6141+
if (!handle)
6142+
return handle;
60986143

60996144
HANDLE hCurrentProcess = ::GetCurrentProcess();
61006145
HANDLE hDupHandle = VMA_NULL;
6101-
if (!::DuplicateHandle(hCurrentProcess, m_hHandle, hTargetProcess ? hTargetProcess : hCurrentProcess, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
6146+
if (!::DuplicateHandle(hCurrentProcess, handle, hTargetProcess ? hTargetProcess : hCurrentProcess, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
61026147
{
61036148
VMA_ASSERT(0 && "Failed to duplicate handle.");
61046149
}
61056150
return hDupHandle;
61066151
}
6107-
operator bool() const noexcept { return m_hHandle != VMA_NULL; }
6108-
61096152
private:
6110-
HANDLE m_hHandle;
6153+
std::atomic<HANDLE> m_hHandle;
61116154
};
61126155
#else
61136156
class VmaWin32Handle
61146157
{
6158+
// ABI compatibility
61156159
void* placeholder = VMA_NULL;
61166160
};
61176161
#endif // VK_USE_PLATFORM_WIN32_KHR
@@ -6186,6 +6230,7 @@ class VmaDeviceMemoryBlock
61866230
#ifdef VK_USE_PLATFORM_WIN32_KHR
61876231
VkResult CreateWin32Handle(
61886232
const VmaAllocator hAllocator,
6233+
decltype(&vkGetMemoryWin32HandleKHR) pvkGetMemoryWin32HandleKHR,
61896234
HANDLE hTargetProcess,
61906235
HANDLE* pHandle)noexcept;
61916236
#endif // VK_USE_PLATFORM_WIN32_KHR
@@ -6310,7 +6355,7 @@ struct VmaAllocation_T
63106355
void* m_pMappedData; // Not null means memory is mapped.
63116356
VmaAllocation_T* m_Prev;
63126357
VmaAllocation_T* m_Next;
6313-
VmaWin32Handle m_Handle; // Win32 handle
6358+
mutable VmaWin32Handle m_Handle; // Win32 handle
63146359
};
63156360
union
63166361
{
@@ -10740,34 +10785,10 @@ VkResult VmaDeviceMemoryBlock::BindImageMemory(
1074010785
}
1074110786

1074210787
#ifdef VK_USE_PLATFORM_WIN32_KHR
10743-
VkResult VmaDeviceMemoryBlock::CreateWin32Handle(const VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
10788+
VkResult VmaDeviceMemoryBlock::CreateWin32Handle(const VmaAllocator hAllocator, decltype(&vkGetMemoryWin32HandleKHR) pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
1074410789
{
1074510790
VMA_ASSERT(pHandle);
10746-
*pHandle = VMA_NULL;
10747-
10748-
// relieves the mutex
10749-
if (m_Handle)
10750-
{
10751-
*pHandle = m_Handle.Duplicate(hTargetProcess);
10752-
return VK_SUCCESS;
10753-
}
10754-
10755-
VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
10756-
if (m_Handle)
10757-
{
10758-
*pHandle = m_Handle.Duplicate(hTargetProcess);
10759-
return VK_SUCCESS;
10760-
}
10761-
10762-
// Do we pass the function manually or use the one from the allocator?
10763-
VkResult res = m_Handle.Init(hAllocator->m_hDevice, m_hMemory, &vkGetMemoryWin32HandleKHR);
10764-
if (res != VK_SUCCESS)
10765-
{
10766-
return res;
10767-
}
10768-
10769-
*pHandle = m_Handle.Duplicate(hTargetProcess);
10770-
return VK_SUCCESS;
10791+
return m_Handle.GetHandle(hAllocator->m_hDevice, m_hMemory, &vkGetMemoryWin32HandleKHR, hTargetProcess, pHandle);
1077110792
}
1077210793
#endif // VK_USE_PLATFORM_WIN32_KHR
1077310794
#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS
@@ -11071,14 +11092,16 @@ void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
1107111092
}
1107211093
}
1107311094
#ifdef VK_USE_PLATFORM_WIN32_KHR
11074-
inline VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) const noexcept
11095+
VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) const noexcept
1107511096
{
11097+
// Where do we get this function from?
11098+
auto pvkGetMemoryWin32HandleKHR = &vkGetMemoryWin32HandleKHR;
1107611099
switch (m_Type)
1107711100
{
1107811101
case ALLOCATION_TYPE_BLOCK:
11079-
return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, hTargetProcess, pHandle);
11102+
return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle);
1108011103
case ALLOCATION_TYPE_DEDICATED:
11081-
// return m_DedicatedAllocation.m_hMemory;
11104+
return m_DedicatedAllocation.m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle);
1108211105
default:
1108311106
VMA_ASSERT(0);
1108411107
return VK_ERROR_FEATURE_NOT_PRESENT;

0 commit comments

Comments
 (0)