mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-22 10:17:01 +08:00
Add support for IPC handles with implicit scaling
When using implicit scaling, device allocations may have more than one internal allocation created internally. In that case, a separate dma-buf handle per internal allocation needs to be exported. So introduced two driver experimental extensions to export and import more than one IPC handle: - zexMemGetIpcHandles - zexMemOpenIpcHandles Related-To: LOCI-2919 Signed-off-by: Jaime Arteaga <jaime.a.arteaga.molina@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
c0de4fd243
commit
3f26f45c10
@@ -7,3 +7,23 @@
|
|||||||
|
|
||||||
#include "level_zero/api/driver_experimental/public/zex_api.h"
|
#include "level_zero/api/driver_experimental/public/zex_api.h"
|
||||||
#include "level_zero/core/source/context/context.h"
|
#include "level_zero/core/source/context/context.h"
|
||||||
|
|
||||||
|
ZE_APIEXPORT ze_result_t ZE_APICALL
|
||||||
|
zexMemGetIpcHandles(
|
||||||
|
ze_context_handle_t hContext,
|
||||||
|
const void *ptr,
|
||||||
|
uint32_t *numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles) {
|
||||||
|
return L0::Context::fromHandle(hContext)->getIpcMemHandles(ptr, numIpcHandles, pIpcHandles);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZE_APIEXPORT ze_result_t ZE_APICALL
|
||||||
|
zexMemOpenIpcHandles(
|
||||||
|
ze_context_handle_t hContext,
|
||||||
|
ze_device_handle_t hDevice,
|
||||||
|
uint32_t numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles,
|
||||||
|
ze_ipc_memory_flags_t flags,
|
||||||
|
void **pptr) {
|
||||||
|
return L0::Context::fromHandle(hContext)->openIpcMemHandles(hDevice, numIpcHandles, pIpcHandles, flags, pptr);
|
||||||
|
}
|
||||||
@@ -17,6 +17,71 @@ extern "C" {
|
|||||||
|
|
||||||
#include "level_zero/api/driver_experimental/public/zex_api.h"
|
#include "level_zero/api/driver_experimental/public/zex_api.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef ZEX_MEM_IPC_HANDLES_NAME
|
||||||
|
/// @brief Multiple IPC handles driver extension name
|
||||||
|
#define ZEX_MEM_IPC_HANDLES_NAME "ZEX_mem_ipc_handles"
|
||||||
|
#endif // ZEX_MEM_IPC_HANDLES_NAME
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Multiple IPC handles driver extension Version(s)
|
||||||
|
typedef enum _zex_mem_ipc_handles_version_t {
|
||||||
|
ZEX_MEM_IPC_HANDLES_VERSION_1_0 = ZE_MAKE_VERSION(1, 0), ///< version 1.0
|
||||||
|
ZEX_MEM_IPC_HANDLES_VERSION_CURRENT = ZE_MAKE_VERSION(1, 0), ///< latest known version
|
||||||
|
ZEX_MEM_IPC_HANDLES_VERSION_FORCE_UINT32 = 0x7fffffff
|
||||||
|
|
||||||
|
} zex_mem_ipc_handles_version_t;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Returns an array IPC memory handles for the specified allocation
|
||||||
|
///
|
||||||
|
/// @details
|
||||||
|
/// - Takes a pointer to a device memory allocation and returns an array of
|
||||||
|
// IPC memory handle for exporting it for use in another process.
|
||||||
|
/// - The application may call this function from simultaneous threads.
|
||||||
|
/// - The implementation of this function must be thread-safe.
|
||||||
|
///
|
||||||
|
/// @returns
|
||||||
|
/// - ::ZE_RESULT_SUCCESS
|
||||||
|
/// - ::ZE_RESULT_ERROR_INVALID_ARGUMENT
|
||||||
|
/// + `ptr` not known
|
||||||
|
ZE_APIEXPORT ze_result_t ZE_APICALL
|
||||||
|
zexMemGetIpcHandles(
|
||||||
|
ze_context_handle_t hContext, ///< [in] handle of the context object
|
||||||
|
const void *ptr, ///< [in] pointer to the device memory allocation
|
||||||
|
uint32_t *numIpcHandles, ///< [in,out] number of IPC handles associated with the allocation
|
||||||
|
///< if numIpcHandles is zero, then the driver shall update the value with the
|
||||||
|
///< total number of IPC handles associated with the allocation.
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles ///< [in,out][optional][range(0, *numIpcHandles)] returned array of IPC memory handles
|
||||||
|
);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Creates an allocation associated with an array of IPC memory handles
|
||||||
|
/// imported from another process.
|
||||||
|
///
|
||||||
|
/// @details
|
||||||
|
/// - Takes an array of IPC memory handles from a remote process and associates it
|
||||||
|
/// with a device pointer usable in this process.
|
||||||
|
/// - The device pointer in this process should not be freed with
|
||||||
|
/// ::zeMemFree, but rather with ::zeMemCloseIpcHandle.
|
||||||
|
/// - The application may call this function from simultaneous threads.
|
||||||
|
/// - The implementation of this function must be thread-safe.
|
||||||
|
///
|
||||||
|
/// @returns
|
||||||
|
/// - ::ZE_RESULT_SUCCESS
|
||||||
|
/// - ::ZE_RESULT_ERROR_INVALID_ARGUMENT
|
||||||
|
/// + handles not known
|
||||||
|
ZE_APIEXPORT ze_result_t ZE_APICALL
|
||||||
|
zexMemOpenIpcHandles(
|
||||||
|
ze_context_handle_t hContext, ///< [in] handle of the context object
|
||||||
|
ze_device_handle_t hDevice, ///< [in] handle of the device to associate with the IPC memory handle
|
||||||
|
uint32_t numIpcHandles, ///< [in] number of IPC handles associated with the allocation
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles, ///< [in][range(0, *numIpcHandles)] array of IPC memory handles
|
||||||
|
ze_ipc_memory_flags_t flags, ///< [in] flags controlling the operation.
|
||||||
|
///< must be 0 (default) or a valid combination of ::ze_ipc_memory_flag_t.
|
||||||
|
void **pptr ///< [out] pointer to device allocation in this process
|
||||||
|
);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020-2021 Intel Corporation
|
* Copyright (C) 2020-2022 Intel Corporation
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
@@ -8,3 +8,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <level_zero/ze_api.h>
|
#include <level_zero/ze_api.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -71,6 +71,20 @@ struct Context : _ze_context_handle_t {
|
|||||||
virtual ze_result_t closeIpcMemHandle(const void *ptr) = 0;
|
virtual ze_result_t closeIpcMemHandle(const void *ptr) = 0;
|
||||||
virtual ze_result_t getIpcMemHandle(const void *ptr,
|
virtual ze_result_t getIpcMemHandle(const void *ptr,
|
||||||
ze_ipc_mem_handle_t *pIpcHandle) = 0;
|
ze_ipc_mem_handle_t *pIpcHandle) = 0;
|
||||||
|
virtual ze_result_t
|
||||||
|
getIpcMemHandles(
|
||||||
|
const void *ptr,
|
||||||
|
uint32_t *numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles) = 0;
|
||||||
|
|
||||||
|
virtual ze_result_t
|
||||||
|
openIpcMemHandles(
|
||||||
|
ze_device_handle_t hDevice,
|
||||||
|
uint32_t numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles,
|
||||||
|
ze_ipc_memory_flags_t flags,
|
||||||
|
void **pptr) = 0;
|
||||||
|
|
||||||
virtual ze_result_t openIpcMemHandle(ze_device_handle_t hDevice,
|
virtual ze_result_t openIpcMemHandle(ze_device_handle_t hDevice,
|
||||||
ze_ipc_mem_handle_t handle,
|
ze_ipc_mem_handle_t handle,
|
||||||
ze_ipc_memory_flags_t flags,
|
ze_ipc_memory_flags_t flags,
|
||||||
|
|||||||
@@ -429,6 +429,31 @@ ze_result_t ContextImp::getIpcMemHandle(const void *ptr,
|
|||||||
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ze_result_t ContextImp::getIpcMemHandles(const void *ptr,
|
||||||
|
uint32_t *numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles) {
|
||||||
|
NEO::SvmAllocationData *allocData = this->driverHandle->svmAllocsManager->getSVMAlloc(ptr);
|
||||||
|
if (allocData) {
|
||||||
|
auto alloc = allocData->gpuAllocations.getDefaultGraphicsAllocation();
|
||||||
|
uint32_t numHandles = alloc->getNumHandles();
|
||||||
|
if (pIpcHandles == nullptr) {
|
||||||
|
*numIpcHandles = numHandles;
|
||||||
|
return ZE_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numHandles; i++) {
|
||||||
|
int handle = static_cast<int>(allocData->gpuAllocations.getDefaultGraphicsAllocation()->peekInternalHandle(this->driverHandle->getMemoryManager(), i));
|
||||||
|
memcpy_s(reinterpret_cast<void *>(pIpcHandles[i].data),
|
||||||
|
sizeof(ze_ipc_mem_handle_t),
|
||||||
|
&handle,
|
||||||
|
sizeof(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZE_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
ze_result_t ContextImp::openIpcMemHandle(ze_device_handle_t hDevice,
|
ze_result_t ContextImp::openIpcMemHandle(ze_device_handle_t hDevice,
|
||||||
ze_ipc_mem_handle_t pIpcHandle,
|
ze_ipc_mem_handle_t pIpcHandle,
|
||||||
ze_ipc_memory_flags_t flags,
|
ze_ipc_memory_flags_t flags,
|
||||||
@@ -447,6 +472,29 @@ ze_result_t ContextImp::openIpcMemHandle(ze_device_handle_t hDevice,
|
|||||||
return ZE_RESULT_SUCCESS;
|
return ZE_RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ze_result_t ContextImp::openIpcMemHandles(ze_device_handle_t hDevice,
|
||||||
|
uint32_t numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles,
|
||||||
|
ze_ipc_memory_flags_t flags,
|
||||||
|
void **pptr) {
|
||||||
|
std::vector<NEO::osHandle> handles;
|
||||||
|
for (uint32_t i = 0; i < numIpcHandles; i++) {
|
||||||
|
uint64_t handle = 0;
|
||||||
|
memcpy_s(&handle,
|
||||||
|
sizeof(handle),
|
||||||
|
reinterpret_cast<void *>(pIpcHandles[i].data),
|
||||||
|
sizeof(handle));
|
||||||
|
handles.push_back(static_cast<NEO::osHandle>(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
*pptr = this->driverHandle->importFdHandles(hDevice, flags, handles, nullptr);
|
||||||
|
if (nullptr == *pptr) {
|
||||||
|
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZE_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
ze_result_t EventPoolImp::closeIpcHandle() {
|
ze_result_t EventPoolImp::closeIpcHandle() {
|
||||||
return this->destroy();
|
return this->destroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,21 @@ struct ContextImp : Context {
|
|||||||
ze_ipc_mem_handle_t handle,
|
ze_ipc_mem_handle_t handle,
|
||||||
ze_ipc_memory_flags_t flags,
|
ze_ipc_memory_flags_t flags,
|
||||||
void **ptr) override;
|
void **ptr) override;
|
||||||
|
|
||||||
|
ze_result_t
|
||||||
|
getIpcMemHandles(
|
||||||
|
const void *ptr,
|
||||||
|
uint32_t *numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles) override;
|
||||||
|
|
||||||
|
ze_result_t
|
||||||
|
openIpcMemHandles(
|
||||||
|
ze_device_handle_t hDevice,
|
||||||
|
uint32_t numIpcHandles,
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles,
|
||||||
|
ze_ipc_memory_flags_t flags,
|
||||||
|
void **pptr) override;
|
||||||
|
|
||||||
ze_result_t getMemAllocProperties(const void *ptr,
|
ze_result_t getMemAllocProperties(const void *ptr,
|
||||||
ze_memory_allocation_properties_t *pMemAllocProperties,
|
ze_memory_allocation_properties_t *pMemAllocProperties,
|
||||||
ze_device_handle_t *phDevice) override;
|
ze_device_handle_t *phDevice) override;
|
||||||
|
|||||||
@@ -459,6 +459,46 @@ void *DriverHandleImp::importFdHandle(ze_device_handle_t hDevice, ze_ipc_memory_
|
|||||||
return reinterpret_cast<void *>(alloc->getGpuAddress());
|
return reinterpret_cast<void *>(alloc->getGpuAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *DriverHandleImp::importFdHandles(ze_device_handle_t hDevice, ze_ipc_memory_flags_t flags, std::vector<NEO::osHandle> handles, NEO::GraphicsAllocation **pAlloc) {
|
||||||
|
auto neoDevice = Device::fromHandle(hDevice)->getNEODevice();
|
||||||
|
NEO::AllocationProperties unifiedMemoryProperties{neoDevice->getRootDeviceIndex(),
|
||||||
|
MemoryConstants::pageSize,
|
||||||
|
NEO::AllocationType::BUFFER,
|
||||||
|
neoDevice->getDeviceBitfield()};
|
||||||
|
unifiedMemoryProperties.subDevicesBitfield = neoDevice->getDeviceBitfield();
|
||||||
|
|
||||||
|
NEO::GraphicsAllocation *alloc =
|
||||||
|
this->getMemoryManager()->createGraphicsAllocationFromMultipleSharedHandles(handles,
|
||||||
|
unifiedMemoryProperties,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
|
if (alloc == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEO::SvmAllocationData allocData(neoDevice->getRootDeviceIndex());
|
||||||
|
allocData.gpuAllocations.addAllocation(alloc);
|
||||||
|
allocData.cpuAllocation = nullptr;
|
||||||
|
allocData.size = alloc->getUnderlyingBufferSize();
|
||||||
|
allocData.memoryType = InternalMemoryType::DEVICE_UNIFIED_MEMORY;
|
||||||
|
allocData.device = neoDevice;
|
||||||
|
if (flags & ZE_DEVICE_MEM_ALLOC_FLAG_BIAS_UNCACHED) {
|
||||||
|
allocData.allocationFlagsProperty.flags.locallyUncachedResource = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & ZE_IPC_MEMORY_FLAG_BIAS_UNCACHED) {
|
||||||
|
allocData.allocationFlagsProperty.flags.locallyUncachedResource = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->getSvmAllocsManager()->insertSVMAlloc(allocData);
|
||||||
|
|
||||||
|
if (pAlloc) {
|
||||||
|
*pAlloc = alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<void *>(alloc->getGpuAddress());
|
||||||
|
}
|
||||||
|
|
||||||
NEO::GraphicsAllocation *DriverHandleImp::getPeerAllocation(Device *device,
|
NEO::GraphicsAllocation *DriverHandleImp::getPeerAllocation(Device *device,
|
||||||
NEO::SvmAllocationData *allocData,
|
NEO::SvmAllocationData *allocData,
|
||||||
void *basePtr,
|
void *basePtr,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ struct DriverHandleImp : public DriverHandle {
|
|||||||
NEO::MemoryManager *getMemoryManager() override;
|
NEO::MemoryManager *getMemoryManager() override;
|
||||||
void setMemoryManager(NEO::MemoryManager *memoryManager) override;
|
void setMemoryManager(NEO::MemoryManager *memoryManager) override;
|
||||||
MOCKABLE_VIRTUAL void *importFdHandle(ze_device_handle_t hDevice, ze_ipc_memory_flags_t flags, uint64_t handle, NEO::GraphicsAllocation **pAlloc);
|
MOCKABLE_VIRTUAL void *importFdHandle(ze_device_handle_t hDevice, ze_ipc_memory_flags_t flags, uint64_t handle, NEO::GraphicsAllocation **pAlloc);
|
||||||
|
MOCKABLE_VIRTUAL void *importFdHandles(ze_device_handle_t hDevice, ze_ipc_memory_flags_t flags, std::vector<NEO::osHandle> handles, NEO::GraphicsAllocation **pAlloc);
|
||||||
MOCKABLE_VIRTUAL void *importNTHandle(ze_device_handle_t hDevice, void *handle);
|
MOCKABLE_VIRTUAL void *importNTHandle(ze_device_handle_t hDevice, void *handle);
|
||||||
ze_result_t checkMemoryAccessFromDevice(Device *device, const void *ptr) override;
|
ze_result_t checkMemoryAccessFromDevice(Device *device, const void *ptr) override;
|
||||||
NEO::SVMAllocsManager *getSvmAllocsManager() override;
|
NEO::SVMAllocsManager *getSvmAllocsManager() override;
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ std::unordered_map<std::string, void *> getExtensionFunctionsLookupMap() {
|
|||||||
addToMap(lookupMap, zexDriverGetHostPointerBaseAddress);
|
addToMap(lookupMap, zexDriverGetHostPointerBaseAddress);
|
||||||
|
|
||||||
addToMap(lookupMap, zexKernelGetBaseAddress);
|
addToMap(lookupMap, zexKernelGetBaseAddress);
|
||||||
|
|
||||||
|
addToMap(lookupMap, zexMemGetIpcHandles);
|
||||||
|
addToMap(lookupMap, zexMemOpenIpcHandles);
|
||||||
#undef addToMap
|
#undef addToMap
|
||||||
|
|
||||||
return lookupMap;
|
return lookupMap;
|
||||||
|
|||||||
@@ -18,65 +18,59 @@ int sv[CHILDPROCESSES][2];
|
|||||||
extern bool verbose;
|
extern bool verbose;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
|
|
||||||
size_t allocSize = 4096 + 7; // +7 to break alignment and make it harder
|
size_t allocSize = 131072 + 7; // +7 to break alignment and make it harder
|
||||||
|
|
||||||
static int sendmsg_fd(int socket, int fd) {
|
static int sendmsgForIpcHandle(int socket, int fd, char *payload) {
|
||||||
char sendBuf[sizeof(ze_ipc_mem_handle_t)] = {};
|
char sendBuf[ZE_MAX_IPC_HANDLE_SIZE] = {};
|
||||||
char cmsgBuf[CMSG_SPACE(sizeof(ze_ipc_mem_handle_t))];
|
memcpy(sendBuf, payload, sizeof(sendBuf));
|
||||||
|
char cmsgBuf[CMSG_SPACE(ZE_MAX_IPC_HANDLE_SIZE)];
|
||||||
|
|
||||||
struct iovec msgBuffer;
|
struct iovec msgBuffer = {};
|
||||||
msgBuffer.iov_base = sendBuf;
|
msgBuffer.iov_base = sendBuf;
|
||||||
msgBuffer.iov_len = sizeof(*sendBuf);
|
msgBuffer.iov_len = ZE_MAX_IPC_HANDLE_SIZE;
|
||||||
|
|
||||||
struct msghdr msgHeader = {};
|
struct msghdr msgHeader = {};
|
||||||
msgHeader.msg_iov = &msgBuffer;
|
msgHeader.msg_iov = &msgBuffer;
|
||||||
msgHeader.msg_iovlen = 1;
|
msgHeader.msg_iovlen = 1;
|
||||||
msgHeader.msg_control = cmsgBuf;
|
msgHeader.msg_control = cmsgBuf;
|
||||||
msgHeader.msg_controllen = CMSG_LEN(sizeof(fd));
|
msgHeader.msg_controllen = CMSG_LEN(sizeof(fd));
|
||||||
|
|
||||||
struct cmsghdr *controlHeader = CMSG_FIRSTHDR(&msgHeader);
|
struct cmsghdr *controlHeader = CMSG_FIRSTHDR(&msgHeader);
|
||||||
controlHeader->cmsg_type = SCM_RIGHTS;
|
controlHeader->cmsg_type = SCM_RIGHTS;
|
||||||
controlHeader->cmsg_level = SOL_SOCKET;
|
controlHeader->cmsg_level = SOL_SOCKET;
|
||||||
controlHeader->cmsg_len = CMSG_LEN(sizeof(fd));
|
controlHeader->cmsg_len = CMSG_LEN(sizeof(fd));
|
||||||
|
|
||||||
*(int *)CMSG_DATA(controlHeader) = fd;
|
*(int *)CMSG_DATA(controlHeader) = fd;
|
||||||
ssize_t bytesSent = sendmsg(socket, &msgHeader, 0);
|
ssize_t bytesSent = sendmsg(socket, &msgHeader, 0);
|
||||||
if (bytesSent < 0) {
|
if (bytesSent < 0) {
|
||||||
|
std::cerr << "Error on sendmsgForIpcHandle " << strerror(errno) << "\n";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static int recvmsgForIpcHandle(int socket, char *payload) {
|
||||||
static int recvmsg_fd(int socket) {
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
char recvBuf[sizeof(ze_ipc_mem_handle_t)] = {};
|
char recvBuf[ZE_MAX_IPC_HANDLE_SIZE] = {};
|
||||||
char cmsgBuf[CMSG_SPACE(sizeof(ze_ipc_mem_handle_t))];
|
char cmsgBuf[CMSG_SPACE(ZE_MAX_IPC_HANDLE_SIZE)];
|
||||||
|
|
||||||
struct iovec msgBuffer;
|
struct iovec msgBuffer;
|
||||||
msgBuffer.iov_base = recvBuf;
|
msgBuffer.iov_base = recvBuf;
|
||||||
msgBuffer.iov_len = sizeof(recvBuf);
|
msgBuffer.iov_len = ZE_MAX_IPC_HANDLE_SIZE;
|
||||||
|
|
||||||
struct msghdr msgHeader = {};
|
struct msghdr msgHeader = {};
|
||||||
msgHeader.msg_iov = &msgBuffer;
|
msgHeader.msg_iov = &msgBuffer;
|
||||||
msgHeader.msg_iovlen = 1;
|
msgHeader.msg_iovlen = 1;
|
||||||
msgHeader.msg_control = cmsgBuf;
|
msgHeader.msg_control = cmsgBuf;
|
||||||
msgHeader.msg_controllen = CMSG_LEN(sizeof(fd));
|
msgHeader.msg_controllen = CMSG_LEN(sizeof(fd));
|
||||||
|
|
||||||
ssize_t bytesSent = recvmsg(socket, &msgHeader, 0);
|
ssize_t bytesSent = recvmsg(socket, &msgHeader, 0);
|
||||||
if (bytesSent < 0) {
|
if (bytesSent < 0) {
|
||||||
|
std::cerr << "Error on recvmsgForIpcHandle " << strerror(errno) << "\n";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmsghdr *controlHeader = CMSG_FIRSTHDR(&msgHeader);
|
struct cmsghdr *controlHeader = CMSG_FIRSTHDR(&msgHeader);
|
||||||
if (!CMSG_DATA(controlHeader)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memmove(&fd, CMSG_DATA(controlHeader), sizeof(int));
|
memmove(&fd, CMSG_DATA(controlHeader), sizeof(int));
|
||||||
|
memmove(payload, recvBuf, sizeof(recvBuf));
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void initializeProcess(ze_context_handle_t &context,
|
inline void initializeProcess(ze_driver_handle_t &driverHandle,
|
||||||
|
ze_context_handle_t &context,
|
||||||
ze_device_handle_t &device,
|
ze_device_handle_t &device,
|
||||||
ze_command_queue_handle_t &cmdQueue,
|
ze_command_queue_handle_t &cmdQueue,
|
||||||
ze_command_list_handle_t &cmdList) {
|
ze_command_list_handle_t &cmdList) {
|
||||||
@@ -86,7 +80,6 @@ inline void initializeProcess(ze_context_handle_t &context,
|
|||||||
uint32_t driverCount = 0;
|
uint32_t driverCount = 0;
|
||||||
SUCCESS_OR_TERMINATE(zeDriverGet(&driverCount, nullptr));
|
SUCCESS_OR_TERMINATE(zeDriverGet(&driverCount, nullptr));
|
||||||
|
|
||||||
ze_driver_handle_t driverHandle;
|
|
||||||
SUCCESS_OR_TERMINATE(zeDriverGet(&driverCount, &driverHandle));
|
SUCCESS_OR_TERMINATE(zeDriverGet(&driverCount, &driverHandle));
|
||||||
|
|
||||||
ze_context_desc_t contextDesc = {ZE_STRUCTURE_TYPE_CONTEXT_DESC};
|
ze_context_desc_t contextDesc = {ZE_STRUCTURE_TYPE_CONTEXT_DESC};
|
||||||
@@ -137,33 +130,63 @@ inline void initializeProcess(ze_context_handle_t &context,
|
|||||||
SUCCESS_OR_TERMINATE(zeCommandListCreate(context, device, &cmdListDesc, &cmdList));
|
SUCCESS_OR_TERMINATE(zeCommandListCreate(context, device, &cmdListDesc, &cmdList));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef ze_result_t (*pFnzexMemGetIpcHandle)(ze_context_handle_t, const void *, uint32_t *, ze_ipc_mem_handle_t *);
|
||||||
|
typedef ze_result_t (*pFnzexMemOpenIpcHandle)(ze_context_handle_t, ze_device_handle_t, uint32_t, ze_ipc_mem_handle_t *, ze_ipc_memory_flags_t, void **);
|
||||||
|
|
||||||
void run_client(int commSocket, uint32_t clientId) {
|
void run_client(int commSocket, uint32_t clientId) {
|
||||||
std::cout << "Client " << clientId << ", process ID: " << std::dec << getpid() << "\n";
|
std::cout << "Client " << clientId << ", process ID: " << std::dec << getpid() << "\n";
|
||||||
|
|
||||||
|
ze_driver_handle_t driverHandle;
|
||||||
ze_context_handle_t context;
|
ze_context_handle_t context;
|
||||||
ze_device_handle_t device;
|
ze_device_handle_t device;
|
||||||
ze_command_queue_handle_t cmdQueue;
|
ze_command_queue_handle_t cmdQueue;
|
||||||
ze_command_list_handle_t cmdList;
|
ze_command_list_handle_t cmdList;
|
||||||
initializeProcess(context, device, cmdQueue, cmdList);
|
initializeProcess(driverHandle, context, device, cmdQueue, cmdList);
|
||||||
|
|
||||||
char *heapBuffer = new char[allocSize];
|
char *heapBuffer = new char[allocSize];
|
||||||
for (size_t i = 0; i < allocSize; ++i) {
|
for (size_t i = 0; i < allocSize; ++i) {
|
||||||
heapBuffer[i] = static_cast<char>(i + 1);
|
heapBuffer[i] = static_cast<char>(i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the dma_buf from the other process
|
pFnzexMemOpenIpcHandle zexMemOpenIpcHandlePointer = nullptr;
|
||||||
int dma_buf_fd = recvmsg_fd(commSocket);
|
SUCCESS_OR_TERMINATE(zeDriverGetExtensionFunctionAddress(driverHandle, "zexMemOpenIpcHandles", reinterpret_cast<void **>(&zexMemOpenIpcHandlePointer)));
|
||||||
if (dma_buf_fd < 0) {
|
|
||||||
std::cerr << "Failing to get dma_buf fd from server\n";
|
// receive the IPC handle for the memory from the other process
|
||||||
|
std::vector<ze_ipc_mem_handle_t> pIpcHandles;
|
||||||
|
|
||||||
|
char payload[ZE_MAX_IPC_HANDLE_SIZE];
|
||||||
|
int handle = recvmsgForIpcHandle(commSocket, payload);
|
||||||
|
if (handle < 0) {
|
||||||
|
std::cerr << "Failing to get IPC memory handle from server\n";
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
ze_ipc_mem_handle_t pIpcHandle;
|
|
||||||
memcpy(&pIpcHandle, static_cast<void *>(&dma_buf_fd), sizeof(dma_buf_fd));
|
|
||||||
|
|
||||||
// get a memory pointer to the BO associated with the dma_buf
|
// check for the number of ipc (dma-buf) handles sent in the payload
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
memcpy(&numIpcHandles, static_cast<void *>(&payload), sizeof(numIpcHandles));
|
||||||
|
if (numIpcHandles == 0) {
|
||||||
|
std::cerr << "numIpcHandles is zero\n";
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get first handle
|
||||||
|
pIpcHandles.resize(numIpcHandles);
|
||||||
|
memcpy(pIpcHandles[0].data, static_cast<void *>(&handle), sizeof(handle));
|
||||||
|
|
||||||
|
// get rest of handles
|
||||||
|
for (uint32_t h = 1; h < numIpcHandles; h++) {
|
||||||
|
int handle = recvmsgForIpcHandle(commSocket, payload);
|
||||||
|
if (handle < 0) {
|
||||||
|
std::cerr << "Failing to get IPC memory handle from server\n";
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
memcpy(pIpcHandles[h].data, static_cast<void *>(&handle), sizeof(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a memory pointer to the BO associated with the dma_buf handles
|
||||||
void *zeIpcBuffer;
|
void *zeIpcBuffer;
|
||||||
SUCCESS_OR_TERMINATE(zeMemOpenIpcHandle(context, device, pIpcHandle,
|
SUCCESS_OR_TERMINATE(zexMemOpenIpcHandlePointer(context, device, numIpcHandles, pIpcHandles.data(), 0u, &zeIpcBuffer));
|
||||||
0u, &zeIpcBuffer));
|
|
||||||
// Copy from heap to IPC buffer memory
|
// Copy from heap to IPC buffer memory
|
||||||
SUCCESS_OR_TERMINATE(zeCommandListAppendMemoryCopy(cmdList, zeIpcBuffer, heapBuffer, allocSize,
|
SUCCESS_OR_TERMINATE(zeCommandListAppendMemoryCopy(cmdList, zeIpcBuffer, heapBuffer, allocSize,
|
||||||
nullptr, 0, nullptr));
|
nullptr, 0, nullptr));
|
||||||
@@ -182,11 +205,12 @@ void run_client(int commSocket, uint32_t clientId) {
|
|||||||
void run_server(bool &validRet) {
|
void run_server(bool &validRet) {
|
||||||
std::cout << "Server process ID " << std::dec << getpid() << "\n";
|
std::cout << "Server process ID " << std::dec << getpid() << "\n";
|
||||||
|
|
||||||
|
ze_driver_handle_t driverHandle;
|
||||||
ze_context_handle_t context;
|
ze_context_handle_t context;
|
||||||
ze_device_handle_t device;
|
ze_device_handle_t device;
|
||||||
ze_command_queue_handle_t cmdQueue;
|
ze_command_queue_handle_t cmdQueue;
|
||||||
ze_command_list_handle_t cmdList;
|
ze_command_list_handle_t cmdList;
|
||||||
initializeProcess(context, device, cmdQueue, cmdList);
|
initializeProcess(driverHandle, context, device, cmdQueue, cmdList);
|
||||||
|
|
||||||
void *zeBuffer = nullptr;
|
void *zeBuffer = nullptr;
|
||||||
ze_device_mem_alloc_desc_t deviceDesc = {ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC};
|
ze_device_mem_alloc_desc_t deviceDesc = {ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC};
|
||||||
@@ -203,19 +227,39 @@ void run_server(bool &validRet) {
|
|||||||
SUCCESS_OR_TERMINATE(zeCommandQueueSynchronize(cmdQueue, std::numeric_limits<uint64_t>::max()));
|
SUCCESS_OR_TERMINATE(zeCommandQueueSynchronize(cmdQueue, std::numeric_limits<uint64_t>::max()));
|
||||||
SUCCESS_OR_TERMINATE(zeCommandListReset(cmdList));
|
SUCCESS_OR_TERMINATE(zeCommandListReset(cmdList));
|
||||||
|
|
||||||
// Get a dma_buf for the previously allocated pointer
|
// Get the IPC handles for the previously allocated pointer
|
||||||
ze_ipc_mem_handle_t pIpcHandle;
|
pFnzexMemGetIpcHandle zexMemGetIpcHandlePointer = nullptr;
|
||||||
SUCCESS_OR_TERMINATE(zeMemGetIpcHandle(context, zeBuffer, &pIpcHandle));
|
SUCCESS_OR_TERMINATE(zeDriverGetExtensionFunctionAddress(driverHandle, "zexMemGetIpcHandles", reinterpret_cast<void **>(&zexMemGetIpcHandlePointer)));
|
||||||
|
|
||||||
// Pass the dma_buf to the other process
|
std::vector<ze_ipc_mem_handle_t> pIpcHandles;
|
||||||
int dma_buf_fd;
|
|
||||||
memcpy(static_cast<void *>(&dma_buf_fd), &pIpcHandle, sizeof(dma_buf_fd));
|
// get the number of ipc handles associated with the allocation
|
||||||
int commSocket = sv[i][0];
|
uint32_t numIpcHandles = 0;
|
||||||
if (sendmsg_fd(commSocket, static_cast<int>(dma_buf_fd)) < 0) {
|
SUCCESS_OR_TERMINATE(zexMemGetIpcHandlePointer(context, zeBuffer, &numIpcHandles, nullptr));
|
||||||
std::cerr << "Failing to send dma_buf fd to client\n";
|
if (numIpcHandles == 0) {
|
||||||
|
std::cerr << "numIpcHandles is zero\n";
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the handles
|
||||||
|
pIpcHandles.resize(numIpcHandles);
|
||||||
|
SUCCESS_OR_TERMINATE(zexMemGetIpcHandlePointer(context, zeBuffer, &numIpcHandles, pIpcHandles.data()));
|
||||||
|
|
||||||
|
// copy the number of ipc handles to the payload, then transmit each handle to the client
|
||||||
|
char payload[ZE_MAX_IPC_HANDLE_SIZE];
|
||||||
|
memcpy(static_cast<void *>(&payload), &numIpcHandles, sizeof(numIpcHandles));
|
||||||
|
for (uint32_t h = 0; h < numIpcHandles; h++) {
|
||||||
|
int commSocket = sv[i][0];
|
||||||
|
int handle = 0;
|
||||||
|
memcpy(static_cast<void *>(&handle), &pIpcHandles[h].data, sizeof(handle));
|
||||||
|
|
||||||
|
int ret = sendmsgForIpcHandle(commSocket, handle, payload);
|
||||||
|
if (ret < 0) {
|
||||||
|
std::cerr << "Failing to send IPC memory handle to client\n";
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *heapBuffer = new char[allocSize];
|
char *heapBuffer = new char[allocSize];
|
||||||
for (size_t i = 0; i < allocSize; ++i) {
|
for (size_t i = 0; i < allocSize; ++i) {
|
||||||
heapBuffer[i] = static_cast<char>(i + 1);
|
heapBuffer[i] = static_cast<char>(i + 1);
|
||||||
@@ -248,6 +292,14 @@ void run_server(bool &validRet) {
|
|||||||
SUCCESS_OR_TERMINATE(zeCommandQueueExecuteCommandLists(cmdQueue, 1, &cmdList, nullptr));
|
SUCCESS_OR_TERMINATE(zeCommandQueueExecuteCommandLists(cmdQueue, 1, &cmdList, nullptr));
|
||||||
SUCCESS_OR_TERMINATE(zeCommandQueueSynchronize(cmdQueue, std::numeric_limits<uint64_t>::max()));
|
SUCCESS_OR_TERMINATE(zeCommandQueueSynchronize(cmdQueue, std::numeric_limits<uint64_t>::max()));
|
||||||
|
|
||||||
|
char *ipcBuffer = static_cast<char *>(validateBuffer);
|
||||||
|
for (uint32_t h = 0; h < allocSize; h++) {
|
||||||
|
if (static_cast<uint32_t>(ipcBuffer[h]) != static_cast<uint32_t>(heapBuffer[h])) {
|
||||||
|
printf("Error: ipcBuffer %d %d, heapBuffer %d\n", h, static_cast<uint32_t>(ipcBuffer[h]), heapBuffer[h]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validate stack and buffers have the original data from heapBuffer
|
// Validate stack and buffers have the original data from heapBuffer
|
||||||
validRet = (0 == memcmp(heapBuffer, validateBuffer, allocSize));
|
validRet = (0 == memcmp(heapBuffer, validateBuffer, allocSize));
|
||||||
delete[] heapBuffer;
|
delete[] heapBuffer;
|
||||||
|
|||||||
@@ -384,6 +384,7 @@ struct ContextGetIpcHandleMock : public L0::ContextImp {
|
|||||||
class MemoryManagerIpcMock : public NEO::MemoryManager {
|
class MemoryManagerIpcMock : public NEO::MemoryManager {
|
||||||
public:
|
public:
|
||||||
MemoryManagerIpcMock(NEO::ExecutionEnvironment &executionEnvironment) : NEO::MemoryManager(executionEnvironment) {}
|
MemoryManagerIpcMock(NEO::ExecutionEnvironment &executionEnvironment) : NEO::MemoryManager(executionEnvironment) {}
|
||||||
|
NEO::GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
||||||
NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
||||||
void addAllocationToHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
void addAllocationToHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
||||||
void removeAllocationFromHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
void removeAllocationFromHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
||||||
@@ -414,20 +415,63 @@ class MemoryManagerIpcMock : public NEO::MemoryManager {
|
|||||||
void unlockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override{};
|
void unlockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IpcImplicitScalingMockGraphicsAllocation : public NEO::MemoryAllocation {
|
||||||
|
public:
|
||||||
|
using MemoryAllocation::allocationOffset;
|
||||||
|
using MemoryAllocation::allocationType;
|
||||||
|
using MemoryAllocation::aubInfo;
|
||||||
|
using MemoryAllocation::gpuAddress;
|
||||||
|
using MemoryAllocation::MemoryAllocation;
|
||||||
|
using MemoryAllocation::memoryPool;
|
||||||
|
using MemoryAllocation::objectNotResident;
|
||||||
|
using MemoryAllocation::objectNotUsed;
|
||||||
|
using MemoryAllocation::size;
|
||||||
|
using MemoryAllocation::usageInfos;
|
||||||
|
|
||||||
|
IpcImplicitScalingMockGraphicsAllocation()
|
||||||
|
: NEO::MemoryAllocation(0, AllocationType::UNKNOWN, nullptr, 0u, 0, MemoryPool::MemoryNull, MemoryManager::maxOsContextCount) {}
|
||||||
|
|
||||||
|
IpcImplicitScalingMockGraphicsAllocation(void *buffer, size_t sizeIn)
|
||||||
|
: NEO::MemoryAllocation(0, AllocationType::UNKNOWN, buffer, castToUint64(buffer), 0llu, sizeIn, MemoryPool::MemoryNull, MemoryManager::maxOsContextCount) {}
|
||||||
|
|
||||||
|
IpcImplicitScalingMockGraphicsAllocation(void *buffer, uint64_t gpuAddr, size_t sizeIn)
|
||||||
|
: NEO::MemoryAllocation(0, AllocationType::UNKNOWN, buffer, gpuAddr, 0llu, sizeIn, MemoryPool::MemoryNull, MemoryManager::maxOsContextCount) {}
|
||||||
|
|
||||||
|
IpcImplicitScalingMockGraphicsAllocation(uint32_t rootDeviceIndex, void *buffer, size_t sizeIn)
|
||||||
|
: NEO::MemoryAllocation(rootDeviceIndex, AllocationType::UNKNOWN, buffer, castToUint64(buffer), 0llu, sizeIn, MemoryPool::MemoryNull, MemoryManager::maxOsContextCount) {}
|
||||||
|
|
||||||
|
uint32_t getNumHandles() override {
|
||||||
|
return 2u;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class MemoryManagerOpenIpcMock : public MemoryManagerIpcMock {
|
class MemoryManagerOpenIpcMock : public MemoryManagerIpcMock {
|
||||||
public:
|
public:
|
||||||
MemoryManagerOpenIpcMock(NEO::ExecutionEnvironment &executionEnvironment) : MemoryManagerIpcMock(executionEnvironment) {}
|
MemoryManagerOpenIpcMock(NEO::ExecutionEnvironment &executionEnvironment) : MemoryManagerIpcMock(executionEnvironment) {}
|
||||||
|
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryWithProperties(const AllocationProperties &properties) override {
|
||||||
|
auto alloc = new IpcImplicitScalingMockGraphicsAllocation(0,
|
||||||
|
NEO::AllocationType::BUFFER,
|
||||||
|
reinterpret_cast<void *>(sharedHandleAddress++),
|
||||||
|
0x1000,
|
||||||
|
0,
|
||||||
|
sizeof(uint32_t),
|
||||||
|
MemoryPool::System4KBPages);
|
||||||
|
alloc->setGpuBaseAddress(0xabcd);
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override {
|
NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override {
|
||||||
if (failOnCreateGraphicsAllocationFromSharedHandle) {
|
if (failOnCreateGraphicsAllocationFromSharedHandle) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto alloc = new NEO::MockGraphicsAllocation(0,
|
auto alloc = new IpcImplicitScalingMockGraphicsAllocation(0,
|
||||||
NEO::AllocationType::BUFFER,
|
NEO::AllocationType::BUFFER,
|
||||||
reinterpret_cast<void *>(sharedHandleAddress++),
|
reinterpret_cast<void *>(sharedHandleAddress++),
|
||||||
0x1000,
|
0x1000,
|
||||||
0,
|
0,
|
||||||
sizeof(uint32_t),
|
sizeof(uint32_t),
|
||||||
MemoryPool::System4KBPages);
|
MemoryPool::System4KBPages);
|
||||||
alloc->setGpuBaseAddress(0xabcd);
|
alloc->setGpuBaseAddress(0xabcd);
|
||||||
return alloc;
|
return alloc;
|
||||||
}
|
}
|
||||||
@@ -502,5 +546,136 @@ struct MemoryOpenIpcHandleTest : public ::testing::Test {
|
|||||||
std::unique_ptr<ContextIpcMock> context;
|
std::unique_ptr<ContextIpcMock> context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MemoryManagerIpcImplicitScalingMock : public NEO::MemoryManager {
|
||||||
|
public:
|
||||||
|
MemoryManagerIpcImplicitScalingMock(NEO::ExecutionEnvironment &executionEnvironment) : NEO::MemoryManager(executionEnvironment) {}
|
||||||
|
|
||||||
|
NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
||||||
|
void addAllocationToHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
||||||
|
void removeAllocationFromHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
||||||
|
NEO::GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override { return nullptr; };
|
||||||
|
AllocationStatus populateOsHandles(NEO::OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override { return AllocationStatus::Success; };
|
||||||
|
void cleanOsHandles(NEO::OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override{};
|
||||||
|
void freeGraphicsMemoryImpl(NEO::GraphicsAllocation *gfxAllocation) override{};
|
||||||
|
void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation, bool isImportedAllocation) override{};
|
||||||
|
uint64_t getSystemSharedMemory(uint32_t rootDeviceIndex) override { return 0; };
|
||||||
|
uint64_t getLocalMemorySize(uint32_t rootDeviceIndex, uint32_t deviceBitfield) override { return 0; };
|
||||||
|
double getPercentOfGlobalMemoryAvailable(uint32_t rootDeviceIndex) override { return 0; }
|
||||||
|
AddressRange reserveGpuAddress(size_t size, uint32_t rootDeviceIndex) override {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
void freeGpuAddress(AddressRange addressRange, uint32_t rootDeviceIndex) override{};
|
||||||
|
NEO::GraphicsAllocation *createGraphicsAllocation(OsHandleStorage &handleStorage, const NEO::AllocationData &allocationData) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryForNonSvmHostPtr(const NEO::AllocationData &allocationData) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryWithAlignment(const NEO::AllocationData &allocationData) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocateUSMHostGraphicsMemory(const NEO::AllocationData &allocationData) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemory64kb(const NEO::AllocationData &allocationData) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocate32BitGraphicsMemoryImpl(const NEO::AllocationData &allocationData, bool useLocalMemory) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryInDevicePool(const NEO::AllocationData &allocationData, AllocationStatus &status) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryWithGpuVa(const NEO::AllocationData &allocationData) override { return nullptr; };
|
||||||
|
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryForImageImpl(const NEO::AllocationData &allocationData, std::unique_ptr<Gmm> gmm) override { return nullptr; };
|
||||||
|
NEO::GraphicsAllocation *allocateMemoryByKMD(const NEO::AllocationData &allocationData) override { return nullptr; };
|
||||||
|
void *lockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override { return nullptr; };
|
||||||
|
void unlockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override{};
|
||||||
|
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryInPreferredPool(const AllocationProperties &properties, const void *hostPtr) override {
|
||||||
|
auto alloc = new IpcImplicitScalingMockGraphicsAllocation(0,
|
||||||
|
NEO::AllocationType::BUFFER,
|
||||||
|
reinterpret_cast<void *>(sharedHandleAddress++),
|
||||||
|
0x1000,
|
||||||
|
0,
|
||||||
|
sizeof(uint32_t),
|
||||||
|
MemoryPool::System4KBPages);
|
||||||
|
alloc->setGpuBaseAddress(0xabcd);
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEO::GraphicsAllocation *allocateGraphicsMemoryWithProperties(const AllocationProperties &properties) override {
|
||||||
|
auto alloc = new IpcImplicitScalingMockGraphicsAllocation(0,
|
||||||
|
NEO::AllocationType::BUFFER,
|
||||||
|
reinterpret_cast<void *>(sharedHandleAddress++),
|
||||||
|
0x1000,
|
||||||
|
0,
|
||||||
|
sizeof(uint32_t),
|
||||||
|
MemoryPool::System4KBPages);
|
||||||
|
alloc->setGpuBaseAddress(0xabcd);
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEO::GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override {
|
||||||
|
if (failOnCreateGraphicsAllocationFromSharedHandle) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto alloc = new IpcImplicitScalingMockGraphicsAllocation(0,
|
||||||
|
NEO::AllocationType::BUFFER,
|
||||||
|
reinterpret_cast<void *>(sharedHandleAddress++),
|
||||||
|
0x1000,
|
||||||
|
0,
|
||||||
|
sizeof(uint32_t),
|
||||||
|
MemoryPool::System4KBPages);
|
||||||
|
alloc->setGpuBaseAddress(0xabcd);
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeGraphicsMemory(NEO::GraphicsAllocation *alloc, bool isImportedAllocation) override {
|
||||||
|
delete alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t sharedHandleAddress = 0x1234;
|
||||||
|
|
||||||
|
bool failOnCreateGraphicsAllocationFromSharedHandle = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MemoryExportImportImplicitScalingTest : public ::testing::Test {
|
||||||
|
void SetUp() override {
|
||||||
|
DebugManagerStateRestore restorer;
|
||||||
|
DebugManager.flags.EnableImplicitScaling.set(1);
|
||||||
|
|
||||||
|
NEO::MockCompilerEnableGuard mock(true);
|
||||||
|
neoDevice =
|
||||||
|
NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(NEO::defaultHwInfo.get());
|
||||||
|
auto mockBuiltIns = new MockBuiltins();
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns);
|
||||||
|
NEO::DeviceVector devices;
|
||||||
|
devices.push_back(std::unique_ptr<NEO::Device>(neoDevice));
|
||||||
|
driverHandle = std::make_unique<DriverHandleImp>();
|
||||||
|
driverHandle->initialize(std::move(devices));
|
||||||
|
prevMemoryManager = driverHandle->getMemoryManager();
|
||||||
|
currMemoryManager = new MemoryManagerIpcImplicitScalingMock(*neoDevice->executionEnvironment);
|
||||||
|
driverHandle->setMemoryManager(currMemoryManager);
|
||||||
|
|
||||||
|
prevSvmAllocsManager = driverHandle->svmAllocsManager;
|
||||||
|
currSvmAllocsManager = new NEO::SVMAllocsManager(currMemoryManager, false);
|
||||||
|
driverHandle->svmAllocsManager = currSvmAllocsManager;
|
||||||
|
|
||||||
|
device = driverHandle->devices[0];
|
||||||
|
|
||||||
|
context = std::make_unique<ContextIpcMock>(driverHandle.get());
|
||||||
|
EXPECT_NE(context, nullptr);
|
||||||
|
context->getDevices().insert(std::make_pair(device->toHandle(), device));
|
||||||
|
auto neoDevice = device->getNEODevice();
|
||||||
|
context->rootDeviceIndices.push_back(neoDevice->getRootDeviceIndex());
|
||||||
|
context->deviceBitfields.insert({neoDevice->getRootDeviceIndex(), neoDevice->getDeviceBitfield()});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override {
|
||||||
|
driverHandle->svmAllocsManager = prevSvmAllocsManager;
|
||||||
|
delete currSvmAllocsManager;
|
||||||
|
driverHandle->setMemoryManager(prevMemoryManager);
|
||||||
|
delete currMemoryManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEO::SVMAllocsManager *prevSvmAllocsManager;
|
||||||
|
NEO::SVMAllocsManager *currSvmAllocsManager;
|
||||||
|
|
||||||
|
NEO::MemoryManager *prevMemoryManager = nullptr;
|
||||||
|
MemoryManagerIpcImplicitScalingMock *currMemoryManager = nullptr;
|
||||||
|
std::unique_ptr<DriverHandleImp> driverHandle;
|
||||||
|
NEO::MockDevice *neoDevice = nullptr;
|
||||||
|
L0::Device *device = nullptr;
|
||||||
|
std::unique_ptr<ContextIpcMock> context;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ult
|
} // namespace ult
|
||||||
} // namespace L0
|
} // namespace L0
|
||||||
|
|||||||
@@ -205,6 +205,45 @@ HWTEST_F(ImportNTHandle, givenNTHandleWhenCreatingDeviceMemoryThenSuccessIsRetur
|
|||||||
delete device;
|
delete device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWTEST_F(ImportNTHandle, whenCallingCreateGraphicsAllocationFromMultipleSharedHandlesFromOsAgnosticMemoryManagerThenNullptrIsReturned) {
|
||||||
|
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
|
||||||
|
|
||||||
|
ze_device_mem_alloc_desc_t devProperties = {};
|
||||||
|
devProperties.stype = ZE_STRUCTURE_TYPE_DEVICE_MEMORY_PROPERTIES;
|
||||||
|
|
||||||
|
uint64_t imageHandle = 0x1;
|
||||||
|
ze_external_memory_import_win32_handle_t importNTHandle = {};
|
||||||
|
importNTHandle.handle = &imageHandle;
|
||||||
|
importNTHandle.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32;
|
||||||
|
importNTHandle.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMPORT_WIN32;
|
||||||
|
devProperties.pNext = &importNTHandle;
|
||||||
|
|
||||||
|
NEO::MockDevice *neoDevice = nullptr;
|
||||||
|
auto executionEnvironment = NEO::MockDevice::prepareExecutionEnvironment(NEO::defaultHwInfo.get(), 0);
|
||||||
|
executionEnvironment->memoryManager.reset(new MemoryManagerNTHandleMock(*executionEnvironment));
|
||||||
|
|
||||||
|
neoDevice = NEO::MockDevice::createWithExecutionEnvironment<NEO::MockDevice>(NEO::defaultHwInfo.get(), executionEnvironment, 0);
|
||||||
|
|
||||||
|
driverHandle->setMemoryManager(executionEnvironment->memoryManager.get());
|
||||||
|
|
||||||
|
ze_result_t result = ZE_RESULT_SUCCESS;
|
||||||
|
auto device = L0::Device::create(driverHandle.get(), neoDevice, false, &result);
|
||||||
|
|
||||||
|
std::vector<osHandle> handles{6, 7};
|
||||||
|
AllocationProperties properties = {device->getRootDeviceIndex(),
|
||||||
|
true,
|
||||||
|
MemoryConstants::pageSize,
|
||||||
|
AllocationType::BUFFER,
|
||||||
|
false,
|
||||||
|
device->getNEODevice()->getDeviceBitfield()};
|
||||||
|
bool requireSpecificBitness{};
|
||||||
|
bool isHostIpcAllocation{};
|
||||||
|
auto ptr = executionEnvironment->memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, requireSpecificBitness, isHostIpcAllocation);
|
||||||
|
EXPECT_EQ(nullptr, ptr);
|
||||||
|
|
||||||
|
delete device;
|
||||||
|
}
|
||||||
|
|
||||||
HWTEST_F(ImportNTHandle, givenNotExistingNTHandleWhenCreatingDeviceMemoryThenErrorIsReturned) {
|
HWTEST_F(ImportNTHandle, givenNotExistingNTHandleWhenCreatingDeviceMemoryThenErrorIsReturned) {
|
||||||
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
|
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class MemoryManagerEventPoolFailMock : public NEO::MemoryManager {
|
|||||||
void *createMultiGraphicsAllocationInSystemMemoryPool(RootDeviceIndicesContainer &rootDeviceIndices, AllocationProperties &properties, NEO::MultiGraphicsAllocation &multiGraphicsAllocation) override {
|
void *createMultiGraphicsAllocationInSystemMemoryPool(RootDeviceIndicesContainer &rootDeviceIndices, AllocationProperties &properties, NEO::MultiGraphicsAllocation &multiGraphicsAllocation) override {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
||||||
NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
||||||
void addAllocationToHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
void addAllocationToHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
||||||
void removeAllocationFromHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
void removeAllocationFromHostPtrManager(NEO::GraphicsAllocation *memory) override{};
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "level_zero/core/source/cmdlist/cmdlist_hw.h"
|
#include "level_zero/core/source/cmdlist/cmdlist_hw.h"
|
||||||
#include "level_zero/core/source/context/context_imp.h"
|
#include "level_zero/core/source/context/context_imp.h"
|
||||||
#include "level_zero/core/source/device/device_imp.h"
|
#include "level_zero/core/source/device/device_imp.h"
|
||||||
|
#include "level_zero/core/source/driver/driver_handle_imp.h"
|
||||||
#include "level_zero/core/source/driver/host_pointer_manager.h"
|
#include "level_zero/core/source/driver/host_pointer_manager.h"
|
||||||
#include "level_zero/core/source/hw_helpers/l0_hw_helper.h"
|
#include "level_zero/core/source/hw_helpers/l0_hw_helper.h"
|
||||||
#include "level_zero/core/source/image/image.h"
|
#include "level_zero/core/source/image/image.h"
|
||||||
@@ -35,6 +36,215 @@
|
|||||||
namespace L0 {
|
namespace L0 {
|
||||||
namespace ult {
|
namespace ult {
|
||||||
|
|
||||||
|
TEST_F(MemoryExportImportImplicitScalingTest,
|
||||||
|
givenCallToGetIpcHandleWithNotKnownPointerThenInvalidArgumentIsReturned) {
|
||||||
|
|
||||||
|
uint32_t value = 0;
|
||||||
|
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
ze_result_t result = context->getIpcMemHandles(&value, &numIpcHandles, nullptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MemoryExportImportImplicitScalingTest,
|
||||||
|
givenCallToGetIpcHandleWithDeviceAllocationThenIpcHandleIsReturned) {
|
||||||
|
size_t size = 10;
|
||||||
|
size_t alignment = 1u;
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
ze_device_mem_alloc_desc_t deviceDesc = {};
|
||||||
|
ze_result_t result = context->allocDeviceMem(device->toHandle(),
|
||||||
|
&deviceDesc,
|
||||||
|
size, alignment, &ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_NE(nullptr, ptr);
|
||||||
|
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_EQ(numIpcHandles, 2u);
|
||||||
|
|
||||||
|
std::vector<ze_ipc_mem_handle_t> ipcHandles(numIpcHandles);
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data());
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
result = context->freeMem(ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MemoryExportImportImplicitScalingTest,
|
||||||
|
whenCallingOpenIpcHandlesWithIpcHandleThenDeviceAllocationIsReturned) {
|
||||||
|
size_t size = 10;
|
||||||
|
size_t alignment = 1u;
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
ze_device_mem_alloc_desc_t deviceDesc = {};
|
||||||
|
ze_result_t result = context->allocDeviceMem(device->toHandle(),
|
||||||
|
&deviceDesc,
|
||||||
|
size, alignment, &ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_NE(nullptr, ptr);
|
||||||
|
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_EQ(numIpcHandles, 2u);
|
||||||
|
|
||||||
|
std::vector<ze_ipc_mem_handle_t> ipcHandles(numIpcHandles);
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data());
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface());
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::make_unique<MockDriverModelDRM>(512));
|
||||||
|
|
||||||
|
ze_ipc_memory_flags_t flags = {};
|
||||||
|
void *ipcPtr;
|
||||||
|
result = context->openIpcMemHandles(device->toHandle(), numIpcHandles, ipcHandles.data(), flags, &ipcPtr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
result = context->closeIpcMemHandle(ipcPtr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
result = context->freeMem(ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MemoryExportImportImplicitScalingTest,
|
||||||
|
whenCallingImportFdHandlesWithAllocationPointerThenAllocationIsReturned) {
|
||||||
|
size_t size = 10;
|
||||||
|
size_t alignment = 1u;
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
ze_device_mem_alloc_desc_t deviceDesc = {};
|
||||||
|
ze_result_t result = context->allocDeviceMem(device->toHandle(),
|
||||||
|
&deviceDesc,
|
||||||
|
size, alignment, &ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_NE(nullptr, ptr);
|
||||||
|
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_EQ(numIpcHandles, 2u);
|
||||||
|
|
||||||
|
std::vector<ze_ipc_mem_handle_t> ipcHandles(numIpcHandles);
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data());
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface());
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::make_unique<MockDriverModelDRM>(512));
|
||||||
|
|
||||||
|
std::vector<NEO::osHandle> handles;
|
||||||
|
for (uint32_t i = 0; i < numIpcHandles; i++) {
|
||||||
|
uint64_t handle = 0;
|
||||||
|
memcpy_s(&handle,
|
||||||
|
sizeof(handle),
|
||||||
|
reinterpret_cast<void *>(ipcHandles[i].data),
|
||||||
|
sizeof(handle));
|
||||||
|
handles.push_back(static_cast<NEO::osHandle>(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
ze_ipc_memory_flags_t flags = {};
|
||||||
|
void *ipcPtr;
|
||||||
|
NEO::GraphicsAllocation *ipcAlloc = nullptr;
|
||||||
|
DriverHandleImp *driverHandleImp = static_cast<DriverHandleImp *>(context->getDriverHandle());
|
||||||
|
ipcPtr = driverHandleImp->importFdHandles(device->toHandle(), flags, handles, &ipcAlloc);
|
||||||
|
EXPECT_NE(ipcPtr, nullptr);
|
||||||
|
EXPECT_NE(ipcAlloc, nullptr);
|
||||||
|
|
||||||
|
result = context->closeIpcMemHandle(ipcPtr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
result = context->freeMem(ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MemoryExportImportImplicitScalingTest,
|
||||||
|
whenCallingImportFdHandlesWithUncachedFlagAllocationPointerThenAllocationIsReturned) {
|
||||||
|
size_t size = 10;
|
||||||
|
size_t alignment = 1u;
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
ze_device_mem_alloc_desc_t deviceDesc = {};
|
||||||
|
ze_result_t result = context->allocDeviceMem(device->toHandle(),
|
||||||
|
&deviceDesc,
|
||||||
|
size, alignment, &ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_NE(nullptr, ptr);
|
||||||
|
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_EQ(numIpcHandles, 2u);
|
||||||
|
|
||||||
|
std::vector<ze_ipc_mem_handle_t> ipcHandles(numIpcHandles);
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data());
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface());
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::make_unique<MockDriverModelDRM>(512));
|
||||||
|
|
||||||
|
std::vector<NEO::osHandle> handles;
|
||||||
|
for (uint32_t i = 0; i < numIpcHandles; i++) {
|
||||||
|
uint64_t handle = 0;
|
||||||
|
memcpy_s(&handle,
|
||||||
|
sizeof(handle),
|
||||||
|
reinterpret_cast<void *>(ipcHandles[i].data),
|
||||||
|
sizeof(handle));
|
||||||
|
handles.push_back(static_cast<NEO::osHandle>(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
ze_ipc_memory_flags_t flags = {ZE_IPC_MEMORY_FLAG_BIAS_UNCACHED};
|
||||||
|
void *ipcPtr;
|
||||||
|
NEO::GraphicsAllocation *ipcAlloc = nullptr;
|
||||||
|
DriverHandleImp *driverHandleImp = static_cast<DriverHandleImp *>(context->getDriverHandle());
|
||||||
|
ipcPtr = driverHandleImp->importFdHandles(device->toHandle(), flags, handles, &ipcAlloc);
|
||||||
|
EXPECT_NE(ipcPtr, nullptr);
|
||||||
|
EXPECT_NE(ipcAlloc, nullptr);
|
||||||
|
|
||||||
|
result = context->closeIpcMemHandle(ipcPtr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
result = context->freeMem(ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MemoryExportImportImplicitScalingTest,
|
||||||
|
whenCallingGetIpcMemHandlesAndImportFailsThenInvalidArgumentFails) {
|
||||||
|
currMemoryManager->failOnCreateGraphicsAllocationFromSharedHandle = true;
|
||||||
|
|
||||||
|
size_t size = 10;
|
||||||
|
size_t alignment = 1u;
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
ze_device_mem_alloc_desc_t deviceDesc = {};
|
||||||
|
ze_result_t result = context->allocDeviceMem(device->toHandle(),
|
||||||
|
&deviceDesc,
|
||||||
|
size, alignment, &ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_NE(nullptr, ptr);
|
||||||
|
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_EQ(numIpcHandles, 2u);
|
||||||
|
|
||||||
|
std::vector<ze_ipc_mem_handle_t> ipcHandles(numIpcHandles);
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data());
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface());
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::make_unique<MockDriverModelDRM>(512));
|
||||||
|
|
||||||
|
ze_ipc_memory_flags_t flags = {};
|
||||||
|
void *ipcPtr;
|
||||||
|
result = context->openIpcMemHandles(device->toHandle(), numIpcHandles, ipcHandles.data(), flags, &ipcPtr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result);
|
||||||
|
|
||||||
|
result = context->freeMem(ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
}
|
||||||
|
|
||||||
using MemoryTest = Test<DeviceFixture>;
|
using MemoryTest = Test<DeviceFixture>;
|
||||||
|
|
||||||
struct CompressionMemoryTest : public MemoryTest {
|
struct CompressionMemoryTest : public MemoryTest {
|
||||||
@@ -2526,6 +2736,44 @@ struct MemoryFailedOpenIpcHandleTest : public ::testing::Test {
|
|||||||
std::unique_ptr<ContextImp> context;
|
std::unique_ptr<ContextImp> context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MemoryFailedOpenIpcHandleImplicitScalingTest : public ::testing::Test {
|
||||||
|
void SetUp() override {
|
||||||
|
DebugManagerStateRestore restorer;
|
||||||
|
DebugManager.flags.EnableImplicitScaling.set(1);
|
||||||
|
NEO::MockCompilerEnableGuard mock(true);
|
||||||
|
neoDevice =
|
||||||
|
NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(NEO::defaultHwInfo.get());
|
||||||
|
auto mockBuiltIns = new MockBuiltins();
|
||||||
|
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns);
|
||||||
|
NEO::DeviceVector devices;
|
||||||
|
devices.push_back(std::unique_ptr<NEO::Device>(neoDevice));
|
||||||
|
driverHandle = std::make_unique<DriverHandleImp>();
|
||||||
|
driverHandle->initialize(std::move(devices));
|
||||||
|
prevMemoryManager = driverHandle->getMemoryManager();
|
||||||
|
currMemoryManager = new MemoryManagerIpcMock(*neoDevice->executionEnvironment);
|
||||||
|
driverHandle->setMemoryManager(currMemoryManager);
|
||||||
|
device = driverHandle->devices[0];
|
||||||
|
|
||||||
|
context = std::make_unique<ContextImp>(driverHandle.get());
|
||||||
|
EXPECT_NE(context, nullptr);
|
||||||
|
context->getDevices().insert(std::make_pair(device->toHandle(), device));
|
||||||
|
auto neoDevice = device->getNEODevice();
|
||||||
|
context->rootDeviceIndices.push_back(neoDevice->getRootDeviceIndex());
|
||||||
|
context->deviceBitfields.insert({neoDevice->getRootDeviceIndex(), neoDevice->getDeviceBitfield()});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override {
|
||||||
|
driverHandle->setMemoryManager(prevMemoryManager);
|
||||||
|
delete currMemoryManager;
|
||||||
|
}
|
||||||
|
NEO::MemoryManager *prevMemoryManager = nullptr;
|
||||||
|
NEO::MemoryManager *currMemoryManager = nullptr;
|
||||||
|
std::unique_ptr<DriverHandleImp> driverHandle;
|
||||||
|
NEO::MockDevice *neoDevice = nullptr;
|
||||||
|
L0::Device *device = nullptr;
|
||||||
|
std::unique_ptr<ContextImp> context;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_F(MemoryFailedOpenIpcHandleTest,
|
TEST_F(MemoryFailedOpenIpcHandleTest,
|
||||||
givenCallToOpenIpcMemHandleWithNullPtrFromCreateGraphicsAllocationFromSharedHandleThenInvalidArgumentIsReturned) {
|
givenCallToOpenIpcMemHandleWithNullPtrFromCreateGraphicsAllocationFromSharedHandleThenInvalidArgumentIsReturned) {
|
||||||
size_t size = 10;
|
size_t size = 10;
|
||||||
@@ -2553,6 +2801,37 @@ TEST_F(MemoryFailedOpenIpcHandleTest,
|
|||||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MemoryFailedOpenIpcHandleImplicitScalingTest,
|
||||||
|
givenCallToOpenIpcMemHandleWithNullPtrFromCreateGraphicsAllocationFromSharedHandleThenInvalidArgumentIsReturned) {
|
||||||
|
size_t size = 10;
|
||||||
|
size_t alignment = 1u;
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
ze_device_mem_alloc_desc_t deviceDesc = {};
|
||||||
|
ze_result_t result = context->allocDeviceMem(device->toHandle(),
|
||||||
|
&deviceDesc,
|
||||||
|
size, alignment, &ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
EXPECT_NE(nullptr, ptr);
|
||||||
|
|
||||||
|
uint32_t numIpcHandles = 0;
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
std::vector<ze_ipc_mem_handle_t> ipcHandles(numIpcHandles);
|
||||||
|
result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data());
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
|
||||||
|
ze_ipc_memory_flags_t flags = {};
|
||||||
|
void *ipcPtr;
|
||||||
|
result = context->openIpcMemHandles(device->toHandle(), numIpcHandles, ipcHandles.data(), flags, &ipcPtr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result);
|
||||||
|
EXPECT_EQ(ipcPtr, nullptr);
|
||||||
|
|
||||||
|
result = context->freeMem(ptr);
|
||||||
|
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||||
|
}
|
||||||
|
|
||||||
using DeviceMemorySizeTest = Test<DeviceFixture>;
|
using DeviceMemorySizeTest = Test<DeviceFixture>;
|
||||||
|
|
||||||
TEST_F(DeviceMemorySizeTest, givenSizeGreaterThanLimitThenDeviceAllocationFails) {
|
TEST_F(DeviceMemorySizeTest, givenSizeGreaterThanLimitThenDeviceAllocationFails) {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<!---
|
||||||
|
|
||||||
|
Copyright (C) 2022 Intel Corporation
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
# Level Zero GPU Driver Driver Experimental Extensions
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The following document describes the driver experimental extensions implemented in the Level Zero Intel(R) GPU driver. These extensions are meant to test and/or gather feedback on interfaces before they could potentially be added Level Zero specification, as well to provide access to functionality specific to Intel(R) GPUs.
|
||||||
|
|
||||||
|
Access to these extensions is possible through [zeDriverGetExtensionFunctionAddress](https://spec.oneapi.io/level-zero/latest/core/api.html?highlight=zedrivergetextensionfunctionaddress#_CPPv435zeDriverGetExtensionFunctionAddress18ze_driver_handle_tPKcPPv). Sample code:
|
||||||
|
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
typedef ze_result_t (*pFnzexMemGetIpcHandles)(ze_context_handle_t, const void *, uint32_t *, ze_ipc_mem_handle_t *);
|
||||||
|
...
|
||||||
|
|
||||||
|
pFnzexMemGetIpcHandles zexMemOpenIpcHandlePointer = nullptr;
|
||||||
|
ze_result_t res = zeDriverGetExtensionFunctionAddress(hDriver, "zexMemOpenIpcHandles", reinterpret_cast<void **>(&zexMemOpenIpcHandlePointer)));
|
||||||
|
```
|
||||||
|
|
||||||
|
### [Multiple IPC Handles](MULTIPLE_IPC_HANDLES.md)
|
||||||
106
level_zero/doc/experimental_extensions/MULTIPLE_IPC_HANDLES.md
Normal file
106
level_zero/doc/experimental_extensions/MULTIPLE_IPC_HANDLES.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<!---
|
||||||
|
|
||||||
|
Copyright (C) 2022 Intel Corporation
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Multiple IPC handles
|
||||||
|
|
||||||
|
* [Overview](#Overview)
|
||||||
|
* [Definitions](#Definitions)
|
||||||
|
* [Known Issues and Limitations](#Known-Issues-and-Limitations)
|
||||||
|
|
||||||
|
# Overview
|
||||||
|
|
||||||
|
When using multi-tile architectures, Level Zero runtime allocations (i.e. `zeMemAllocDevice`) may be split by the GPU driver into several smaller allocations, each one allocated in a given tile. This is done for instance when using implicit scaling, to equally distribute memory on the available tiles. Although this is done as an internal optimization the application should not be aware of, there are scenarios where the number of internal allocations need to be known by the application. One of those being when exchanging the IPC handles of the runtime allocation with other process. If the allocation has been split into several smaller ones, then each of thse internal allocations would have its own file descriptor, and each of them need to be separately interchanged with the other process.
|
||||||
|
|
||||||
|
Current IPC memory interfaces in the Level Zero specification `zeMemGetIpcHandle` and `zeMemOpenIpcHandle` assume the existence of only one file descriptor, and cannot be used when multiple internal allocations and file descriptors are associated with a single Level Zero allocation.
|
||||||
|
|
||||||
|
This extension provides two new interfaces with which applications can query the number of file descriptors associated with a Level Zero allocation, get those descriptors, and then create a new allocation composed of the exported internal allocations.
|
||||||
|
|
||||||
|
# Definitions
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef ZEX_MEM_IPC_HANDLES_NAME
|
||||||
|
/// @brief Multiple IPC handles driver extension name
|
||||||
|
#define ZEX_MEM_IPC_HANDLES_NAME "ZEX_mem_ipc_handles"
|
||||||
|
#endif // ZEX_MEM_IPC_HANDLES_NAME
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Multiple IPC handles driver extension Version(s)
|
||||||
|
typedef enum _zex_mem_ipc_handles_version_t
|
||||||
|
{
|
||||||
|
ZEX_MEM_IPC_HANDLES_VERSION_1_0 = ZE_MAKE_VERSION( 1, 0 ), ///< version 1.0
|
||||||
|
ZEX_MEM_IPC_HANDLES_VERSION_CURRENT = ZE_MAKE_VERSION( 1, 0 ), ///< latest known version
|
||||||
|
ZEX_MEM_IPC_HANDLES_VERSION_FORCE_UINT32 = 0x7fffffff
|
||||||
|
|
||||||
|
} zex_mem_ipc_handles_version_t;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interfaces
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Returns an array IPC memory handles for the specified allocation
|
||||||
|
///
|
||||||
|
/// @details
|
||||||
|
/// - Takes a pointer to a device memory allocation and returns an array of
|
||||||
|
// IPC memory handle for exporting it for use in another process.
|
||||||
|
/// - The application may call this function from simultaneous threads.
|
||||||
|
/// - The implementation of this function must be thread-safe.
|
||||||
|
///
|
||||||
|
/// @returns
|
||||||
|
/// - ::ZE_RESULT_SUCCESS
|
||||||
|
/// - ::ZE_RESULT_ERROR_INVALID_ARGUMENT
|
||||||
|
/// + ptr` not known
|
||||||
|
ZE_APIEXPORT ze_result_t ZE_APICALL
|
||||||
|
zexMemGetIpcHandles(
|
||||||
|
ze_context_handle_t hContext, ///< [in] handle of the context object
|
||||||
|
const void *ptr, ///< [in] pointer to the device memory allocation
|
||||||
|
uint32_t *numIpcHandles, ///< [in,out] number of IPC handles associated with the allocation
|
||||||
|
///< if numIpcHandles is zero, then the driver shall update the value with the
|
||||||
|
///< total number of IPC handles associated with the allocation.
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles ///< [in,out][optional][range(0, *numIpcHandles)] returned array of IPC memory handles
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Creates an allocation associated with an array of IPC memory handles
|
||||||
|
/// imported from another process.
|
||||||
|
///
|
||||||
|
/// @details
|
||||||
|
/// - Takes an array of IPC memory handles from a remote process and associates it
|
||||||
|
/// with a device pointer usable in this process.
|
||||||
|
/// - The device pointer in this process should not be freed with
|
||||||
|
/// ::zeMemFree, but rather with ::zeMemCloseIpcHandle.
|
||||||
|
/// - The application may call this function from simultaneous threads.
|
||||||
|
/// - The implementation of this function must be thread-safe.
|
||||||
|
///
|
||||||
|
/// @returns
|
||||||
|
/// - ::ZE_RESULT_SUCCESS
|
||||||
|
/// - ::ZE_RESULT_ERROR_INVALID_ARGUMENT
|
||||||
|
/// + handles not known
|
||||||
|
ZE_APIEXPORT ze_result_t ZE_APICALL
|
||||||
|
zexMemOpenIpcHandles(
|
||||||
|
ze_context_handle_t hContext, ///< [in] handle of the context object
|
||||||
|
ze_device_handle_t hDevice, ///< [in] handle of the device to associate with the IPC memory handle
|
||||||
|
uint32_t numIpcHandles, ///< [in] number of IPC handles associated with the allocation
|
||||||
|
ze_ipc_mem_handle_t *pIpcHandles, ///< [in][range(0, *numIpcHandles)] array of IPC memory handles
|
||||||
|
ze_ipc_memory_flags_t flags, ///< [in] flags controlling the operation.
|
||||||
|
///< must be 0 (default) or a valid combination of ::ze_ipc_memory_flag_t.
|
||||||
|
void **pptr ///< [out] pointer to device allocation in this process
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Enums
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
# Known Issues and Limitations
|
||||||
|
|
||||||
|
* Currently supported only on Linux.
|
||||||
|
* Mainly implemented for and validated on Xe HPC (PVC) and XeHP_SDV platforms.
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "shared/source/memory_manager/compression_selector.h"
|
#include "shared/source/memory_manager/compression_selector.h"
|
||||||
#include "shared/source/memory_manager/unified_memory_manager.h"
|
#include "shared/source/memory_manager/unified_memory_manager.h"
|
||||||
#include "shared/source/os_interface/linux/allocator_helper.h"
|
#include "shared/source/os_interface/linux/allocator_helper.h"
|
||||||
|
#include "shared/test/common/fixtures/memory_allocator_multi_device_fixture.h"
|
||||||
#include "shared/test/common/libult/linux/drm_mock_helper.h"
|
#include "shared/test/common/libult/linux/drm_mock_helper.h"
|
||||||
#include "shared/test/common/libult/linux/drm_mock_prelim_context.h"
|
#include "shared/test/common/libult/linux/drm_mock_prelim_context.h"
|
||||||
#include "shared/test/common/libult/linux/drm_query_mock.h"
|
#include "shared/test/common/libult/linux/drm_query_mock.h"
|
||||||
@@ -1550,6 +1551,115 @@ TEST_F(DrmMemoryManagerCopyMemoryToAllocationPrelimTest, givenDrmMemoryManagerWh
|
|||||||
|
|
||||||
typedef Test<DrmMemoryManagerFixturePrelim> DrmMemoryManagerTestPrelim;
|
typedef Test<DrmMemoryManagerFixturePrelim> DrmMemoryManagerTestPrelim;
|
||||||
|
|
||||||
|
TEST_F(DrmMemoryManagerTestPrelim, whenSettingNumHandlesThenTheyAreRetrievedCorrectly) {
|
||||||
|
mock->ioctl_expected.primeFdToHandle = 2;
|
||||||
|
mock->ioctl_expected.gemWait = 1;
|
||||||
|
mock->ioctl_expected.gemClose = 2;
|
||||||
|
|
||||||
|
std::vector<NEO::osHandle> handles{6, 7};
|
||||||
|
size_t size = 65536u * 2;
|
||||||
|
AllocationProperties properties(rootDeviceIndex, true, size, AllocationType::BUFFER_HOST_MEMORY, false, device->getDeviceBitfield());
|
||||||
|
|
||||||
|
auto graphicsAllocation = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
ASSERT_NE(nullptr, graphicsAllocation);
|
||||||
|
|
||||||
|
uint32_t numHandlesExpected = 8;
|
||||||
|
graphicsAllocation->setNumHandles(numHandlesExpected);
|
||||||
|
EXPECT_EQ(graphicsAllocation->getNumHandles(), numHandlesExpected);
|
||||||
|
|
||||||
|
graphicsAllocation->setNumHandles(static_cast<uint32_t>(handles.size()));
|
||||||
|
|
||||||
|
memoryManager->freeGraphicsMemory(graphicsAllocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DrmMemoryManagerTestPrelim, whenCreatingAllocationFromMultipleSharedHandlesAndFindAndReferenceSharedBufferObjectReturnsNonNullThenAllocationSucceeds) {
|
||||||
|
mock->ioctl_expected.primeFdToHandle = 4;
|
||||||
|
mock->ioctl_expected.gemWait = 2;
|
||||||
|
mock->ioctl_expected.gemClose = 2;
|
||||||
|
|
||||||
|
std::vector<NEO::osHandle> handles{6, 7};
|
||||||
|
size_t size = 65536u * 2;
|
||||||
|
AllocationProperties properties(rootDeviceIndex, true, size, AllocationType::BUFFER_HOST_MEMORY, false, device->getDeviceBitfield());
|
||||||
|
|
||||||
|
memoryManager->failOnfindAndReferenceSharedBufferObject = false;
|
||||||
|
auto graphicsAllocation = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
ASSERT_NE(nullptr, graphicsAllocation);
|
||||||
|
|
||||||
|
DrmAllocation *drmAllocation = static_cast<DrmAllocation *>(graphicsAllocation);
|
||||||
|
auto bo = drmAllocation->getBO();
|
||||||
|
EXPECT_EQ(bo->peekHandle(), (int)this->mock->outputHandle);
|
||||||
|
EXPECT_NE(0llu, bo->peekAddress());
|
||||||
|
|
||||||
|
auto graphicsAllocationFromReferencedHandle = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
ASSERT_NE(nullptr, graphicsAllocationFromReferencedHandle);
|
||||||
|
|
||||||
|
DrmAllocation *drmAllocationFromReferencedHandle = static_cast<DrmAllocation *>(graphicsAllocationFromReferencedHandle);
|
||||||
|
auto boFromReferencedHandle = drmAllocationFromReferencedHandle->getBO();
|
||||||
|
EXPECT_EQ(boFromReferencedHandle->peekHandle(), (int)this->mock->outputHandle);
|
||||||
|
EXPECT_NE(0llu, boFromReferencedHandle->peekAddress());
|
||||||
|
|
||||||
|
memoryManager->freeGraphicsMemory(graphicsAllocation);
|
||||||
|
memoryManager->freeGraphicsMemory(graphicsAllocationFromReferencedHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DrmMemoryManagerTestPrelim, whenCreatingAllocationFromMultipleSharedHandlesWithOneHandleThenAllocationSucceeds) {
|
||||||
|
mock->ioctl_expected.primeFdToHandle = 1;
|
||||||
|
mock->ioctl_expected.gemWait = 1;
|
||||||
|
mock->ioctl_expected.gemClose = 1;
|
||||||
|
|
||||||
|
std::vector<NEO::osHandle> handles{6};
|
||||||
|
size_t size = 65536u * 2;
|
||||||
|
AllocationProperties properties(rootDeviceIndex, true, size, AllocationType::BUFFER_HOST_MEMORY, false, device->getDeviceBitfield());
|
||||||
|
|
||||||
|
memoryManager->failOnfindAndReferenceSharedBufferObject = false;
|
||||||
|
auto graphicsAllocation = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
ASSERT_NE(nullptr, graphicsAllocation);
|
||||||
|
|
||||||
|
DrmAllocation *drmAllocation = static_cast<DrmAllocation *>(graphicsAllocation);
|
||||||
|
auto bo = drmAllocation->getBO();
|
||||||
|
EXPECT_EQ(bo->peekHandle(), (int)this->mock->outputHandle);
|
||||||
|
EXPECT_NE(0llu, bo->peekAddress());
|
||||||
|
EXPECT_EQ(1u, bo->getRefCount());
|
||||||
|
|
||||||
|
memoryManager->freeGraphicsMemory(graphicsAllocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DrmMemoryManagerTestPrelim, whenCreatingAllocationFromMultipleSharedHandlesAndIoctlFailsThenNullIsReturned) {
|
||||||
|
mock->ioctl_expected.primeFdToHandle = 1;
|
||||||
|
mock->ioctl_expected.gemWait = 0;
|
||||||
|
mock->ioctl_expected.gemClose = 0;
|
||||||
|
mock->failOnPrimeFdToHandle = true;
|
||||||
|
|
||||||
|
std::vector<NEO::osHandle> handles{6, 7};
|
||||||
|
size_t size = 65536u * 2;
|
||||||
|
AllocationProperties properties(rootDeviceIndex, true, size, AllocationType::BUFFER_HOST_MEMORY, false, device->getDeviceBitfield());
|
||||||
|
|
||||||
|
memoryManager->failOnfindAndReferenceSharedBufferObject = false;
|
||||||
|
auto graphicsAllocation = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
EXPECT_EQ(nullptr, graphicsAllocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DrmMemoryManagerTestPrelim, whenCreatingAllocationFromMultipleSharedHandlesThenAllocationSucceeds) {
|
||||||
|
mock->ioctl_expected.primeFdToHandle = 2;
|
||||||
|
mock->ioctl_expected.gemWait = 1;
|
||||||
|
mock->ioctl_expected.gemClose = 2;
|
||||||
|
|
||||||
|
std::vector<NEO::osHandle> handles{6, 7};
|
||||||
|
size_t size = 65536u * 2;
|
||||||
|
AllocationProperties properties(rootDeviceIndex, true, size, AllocationType::BUFFER_HOST_MEMORY, false, device->getDeviceBitfield());
|
||||||
|
|
||||||
|
auto graphicsAllocation = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
ASSERT_NE(nullptr, graphicsAllocation);
|
||||||
|
|
||||||
|
DrmAllocation *drmAllocation = static_cast<DrmAllocation *>(graphicsAllocation);
|
||||||
|
auto bo = drmAllocation->getBO();
|
||||||
|
EXPECT_EQ(bo->peekHandle(), (int)this->mock->outputHandle);
|
||||||
|
EXPECT_NE(0llu, bo->peekAddress());
|
||||||
|
EXPECT_EQ(1u, bo->getRefCount());
|
||||||
|
|
||||||
|
memoryManager->freeGraphicsMemory(graphicsAllocation);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DrmMemoryManagerTestPrelim, givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButFailsOnMmapFunctionThenReturnNullPtr) {
|
TEST_F(DrmMemoryManagerTestPrelim, givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButFailsOnMmapFunctionThenReturnNullPtr) {
|
||||||
mock->ioctl_expected.gemMmapOffset = 2;
|
mock->ioctl_expected.gemMmapOffset = 2;
|
||||||
this->ioctlResExt = {mock->ioctl_cnt.total, -1};
|
this->ioctlResExt = {mock->ioctl_cnt.total, -1};
|
||||||
|
|||||||
@@ -475,6 +475,21 @@ TEST_F(DrmMemoryManagerTest, whenPeekInternalHandleIsCalledThenBoIsReturend) {
|
|||||||
memoryManager->freeGraphicsMemory(allocation);
|
memoryManager->freeGraphicsMemory(allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DrmMemoryManagerTest, whenPeekInternalHandleWithHandleIdIsCalledThenBoIsReturend) {
|
||||||
|
mock->ioctl_expected.gemUserptr = 1;
|
||||||
|
mock->ioctl_expected.gemWait = 1;
|
||||||
|
mock->ioctl_expected.gemClose = 1;
|
||||||
|
mock->ioctl_expected.handleToPrimeFd = 1;
|
||||||
|
mock->outputFd = 1337;
|
||||||
|
auto allocation = static_cast<DrmAllocation *>(this->memoryManager->allocateGraphicsMemoryWithProperties(createAllocationProperties(rootDeviceIndex, 10 * MemoryConstants::pageSize, true)));
|
||||||
|
ASSERT_NE(allocation->getBO(), nullptr);
|
||||||
|
|
||||||
|
uint32_t handleId = 0;
|
||||||
|
ASSERT_EQ(allocation->peekInternalHandle(this->memoryManager, handleId), static_cast<uint64_t>(1337));
|
||||||
|
|
||||||
|
memoryManager->freeGraphicsMemory(allocation);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DrmMemoryManagerTest, givenDrmContextIdWhenAllocationIsCreatedThenPinWithPassedDrmContextId) {
|
TEST_F(DrmMemoryManagerTest, givenDrmContextIdWhenAllocationIsCreatedThenPinWithPassedDrmContextId) {
|
||||||
mock->ioctl_expected.gemUserptr = 2;
|
mock->ioctl_expected.gemUserptr = 2;
|
||||||
mock->ioctl_expected.execbuffer2 = 1;
|
mock->ioctl_expected.execbuffer2 = 1;
|
||||||
|
|||||||
@@ -552,6 +552,20 @@ TEST_F(Wddm20WithMockGdiDllTests, givenSharedHandleWhenCreateGraphicsAllocationF
|
|||||||
EXPECT_EQ(1u, destroyWithResourceHandleCalled);
|
EXPECT_EQ(1u, destroyWithResourceHandleCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(Wddm20WithMockGdiDllTests, givenSharedHandleWhenCreateGraphicsAllocationFromMultipleSharedHandlesIsCalledThenNullptrIsReturned) {
|
||||||
|
void *pSysMem = (void *)0x1000;
|
||||||
|
std::unique_ptr<Gmm> gmm(new Gmm(getGmmHelper(), pSysMem, 4096u, 0, GMM_RESOURCE_USAGE_OCL_BUFFER, false, {}, true));
|
||||||
|
auto status = setSizesFcn(gmm->gmmResourceInfo.get(), 1u, 1024u, 1u);
|
||||||
|
EXPECT_EQ(0u, status);
|
||||||
|
|
||||||
|
MemoryManagerCreate<WddmMemoryManager> mm(false, false, *executionEnvironment);
|
||||||
|
AllocationProperties properties(0, false, 4096u, AllocationType::SHARED_BUFFER, false, {});
|
||||||
|
|
||||||
|
std::vector<osHandle> handles{ALLOCATION_HANDLE};
|
||||||
|
auto graphicsAllocation = mm.createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
ASSERT_EQ(nullptr, graphicsAllocation);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(Wddm20WithMockGdiDllTests, givenSharedHandleWhenCreateGraphicsAllocationFromSharedHandleIsCalledThenMapGpuVaWithCpuPtrDepensOnBitness) {
|
TEST_F(Wddm20WithMockGdiDllTests, givenSharedHandleWhenCreateGraphicsAllocationFromSharedHandleIsCalledThenMapGpuVaWithCpuPtrDepensOnBitness) {
|
||||||
void *pSysMem = (void *)0x1000;
|
void *pSysMem = (void *)0x1000;
|
||||||
std::unique_ptr<Gmm> gmm(new Gmm(getGmmHelper(), pSysMem, 4096u, 0, GMM_RESOURCE_USAGE_OCL_BUFFER, false, {}, true));
|
std::unique_ptr<Gmm> gmm(new Gmm(getGmmHelper(), pSysMem, 4096u, 0, GMM_RESOURCE_USAGE_OCL_BUFFER, false, {}, true));
|
||||||
|
|||||||
@@ -318,6 +318,25 @@ TEST_F(WddmMemoryManagerSimpleTest, givenMemoryManagerWhenCreateAllocationFromHa
|
|||||||
memoryManager->freeGraphicsMemory(allocation);
|
memoryManager->freeGraphicsMemory(allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WddmMemoryManagerSimpleTest, givenSharedHandleWhenCreateGraphicsAllocationFromMultipleSharedHandlesIsCalledThenNullptrIsReturned) {
|
||||||
|
memoryManager.reset(new MockWddmMemoryManager(false, false, *executionEnvironment));
|
||||||
|
auto handle = 1u;
|
||||||
|
gdi->getQueryResourceInfoArgOut().NumAllocations = 1;
|
||||||
|
std::unique_ptr<Gmm> gmm(new Gmm(rootDeviceEnvironment->getGmmHelper(), nullptr, 0, 0, GMM_RESOURCE_USAGE_OCL_BUFFER, false, {}, true));
|
||||||
|
|
||||||
|
D3DDDI_OPENALLOCATIONINFO allocationInfo;
|
||||||
|
allocationInfo.pPrivateDriverData = gmm->gmmResourceInfo->peekHandle();
|
||||||
|
allocationInfo.hAllocation = ALLOCATION_HANDLE;
|
||||||
|
allocationInfo.PrivateDriverDataSize = sizeof(GMM_RESOURCE_INFO);
|
||||||
|
|
||||||
|
gdi->getOpenResourceArgOut().pOpenAllocationInfo = &allocationInfo;
|
||||||
|
|
||||||
|
AllocationProperties properties(0, false, 0, AllocationType::SHARED_BUFFER, false, false, 0);
|
||||||
|
std::vector<osHandle> handles{handle};
|
||||||
|
auto allocation = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, false);
|
||||||
|
EXPECT_EQ(nullptr, allocation);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(WddmMemoryManagerSimpleTest, givenAllocationPropertiesWhenCreateAllocationFromHandleIsCalledThenCorrectAllocationTypeIsSet) {
|
TEST_F(WddmMemoryManagerSimpleTest, givenAllocationPropertiesWhenCreateAllocationFromHandleIsCalledThenCorrectAllocationTypeIsSet) {
|
||||||
memoryManager.reset(new MockWddmMemoryManager(false, false, *executionEnvironment));
|
memoryManager.reset(new MockWddmMemoryManager(false, false, *executionEnvironment));
|
||||||
auto osHandle = 1u;
|
auto osHandle = 1u;
|
||||||
|
|||||||
@@ -176,6 +176,17 @@ class GraphicsAllocation : public IDNode<GraphicsAllocation> {
|
|||||||
virtual std::string getAllocationInfoString() const;
|
virtual std::string getAllocationInfoString() const;
|
||||||
virtual uint64_t peekInternalHandle(MemoryManager *memoryManager) { return 0llu; }
|
virtual uint64_t peekInternalHandle(MemoryManager *memoryManager) { return 0llu; }
|
||||||
|
|
||||||
|
virtual uint64_t peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId) {
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32_t getNumHandles() {
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setNumHandles(uint32_t numHandles) {
|
||||||
|
}
|
||||||
|
|
||||||
static bool isCpuAccessRequired(AllocationType allocationType) {
|
static bool isCpuAccessRequired(AllocationType allocationType) {
|
||||||
return allocationType == AllocationType::COMMAND_BUFFER ||
|
return allocationType == AllocationType::COMMAND_BUFFER ||
|
||||||
allocationType == AllocationType::CONSTANT_SURFACE ||
|
allocationType == AllocationType::CONSTANT_SURFACE ||
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ class MemoryManager {
|
|||||||
|
|
||||||
virtual bool verifyHandle(osHandle handle, uint32_t rootDeviceIndex, bool) { return true; }
|
virtual bool verifyHandle(osHandle handle, uint32_t rootDeviceIndex, bool) { return true; }
|
||||||
virtual bool isNTHandle(osHandle handle, uint32_t rootDeviceIndex) { return false; }
|
virtual bool isNTHandle(osHandle handle, uint32_t rootDeviceIndex) { return false; }
|
||||||
|
virtual GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) = 0;
|
||||||
virtual GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) = 0;
|
virtual GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) = 0;
|
||||||
virtual void closeSharedHandle(GraphicsAllocation *graphicsAllocation){};
|
virtual void closeSharedHandle(GraphicsAllocation *graphicsAllocation){};
|
||||||
virtual GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) = 0;
|
virtual GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) = 0;
|
||||||
|
|||||||
@@ -223,6 +223,10 @@ GraphicsAllocation *OsAgnosticMemoryManager::allocate32BitGraphicsMemoryImpl(con
|
|||||||
return memoryAllocation;
|
return memoryAllocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsAllocation *OsAgnosticMemoryManager::createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
GraphicsAllocation *OsAgnosticMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
GraphicsAllocation *OsAgnosticMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
||||||
auto graphicsAllocation = createMemoryAllocation(properties.allocationType, nullptr, reinterpret_cast<void *>(1), 1,
|
auto graphicsAllocation = createMemoryAllocation(properties.allocationType, nullptr, reinterpret_cast<void *>(1), 1,
|
||||||
4096u, static_cast<uint64_t>(handle), MemoryPool::SystemCpuInaccessible, properties.rootDeviceIndex,
|
4096u, static_cast<uint64_t>(handle), MemoryPool::SystemCpuInaccessible, properties.rootDeviceIndex,
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ class OsAgnosticMemoryManager : public MemoryManager {
|
|||||||
OsAgnosticMemoryManager(bool aubUsage, ExecutionEnvironment &executionEnvironment);
|
OsAgnosticMemoryManager(bool aubUsage, ExecutionEnvironment &executionEnvironment);
|
||||||
void initialize(bool aubUsage);
|
void initialize(bool aubUsage);
|
||||||
~OsAgnosticMemoryManager() override;
|
~OsAgnosticMemoryManager() override;
|
||||||
|
GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
||||||
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
||||||
GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override { return nullptr; }
|
GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override { return nullptr; }
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ uint64_t DrmAllocation::peekInternalHandle(MemoryManager *memoryManager) {
|
|||||||
return static_cast<uint64_t>((static_cast<DrmMemoryManager *>(memoryManager))->obtainFdFromHandle(getBO()->peekHandle(), this->rootDeviceIndex));
|
return static_cast<uint64_t>((static_cast<DrmMemoryManager *>(memoryManager))->obtainFdFromHandle(getBO()->peekHandle(), this->rootDeviceIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t DrmAllocation::peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId) {
|
||||||
|
return static_cast<uint64_t>((static_cast<DrmMemoryManager *>(memoryManager))->obtainFdFromHandle(getBufferObjectToModify(handleId)->peekHandle(), this->rootDeviceIndex));
|
||||||
|
}
|
||||||
|
|
||||||
void DrmAllocation::setCachePolicy(CachePolicy memType) {
|
void DrmAllocation::setCachePolicy(CachePolicy memType) {
|
||||||
for (auto bo : bufferObjects) {
|
for (auto bo : bufferObjects) {
|
||||||
if (bo != nullptr) {
|
if (bo != nullptr) {
|
||||||
|
|||||||
@@ -78,8 +78,18 @@ class DrmAllocation : public GraphicsAllocation {
|
|||||||
this->bufferObjects.resize(size);
|
this->bufferObjects.resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t getNumHandles() override {
|
||||||
|
return this->numHandles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNumHandles(uint32_t numHandles) override {
|
||||||
|
this->numHandles = numHandles;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t peekInternalHandle(MemoryManager *memoryManager) override;
|
uint64_t peekInternalHandle(MemoryManager *memoryManager) override;
|
||||||
|
|
||||||
|
uint64_t peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId) override;
|
||||||
|
|
||||||
bool setCacheRegion(Drm *drm, CacheRegion regionIndex);
|
bool setCacheRegion(Drm *drm, CacheRegion regionIndex);
|
||||||
bool setCacheAdvice(Drm *drm, size_t regionSize, CacheRegion regionIndex);
|
bool setCacheAdvice(Drm *drm, size_t regionSize, CacheRegion regionIndex);
|
||||||
void setCachePolicy(CachePolicy memType);
|
void setCachePolicy(CachePolicy memType);
|
||||||
@@ -107,6 +117,7 @@ class DrmAllocation : public GraphicsAllocation {
|
|||||||
StackVec<uint32_t, 1> registeredBoBindHandles;
|
StackVec<uint32_t, 1> registeredBoBindHandles;
|
||||||
MemAdviseFlags enabledMemAdviseFlags{};
|
MemAdviseFlags enabledMemAdviseFlags{};
|
||||||
StackVec<MemoryToUnmap, 1> memoryToUnmap;
|
StackVec<MemoryToUnmap, 1> memoryToUnmap;
|
||||||
|
uint32_t numHandles = 0u;
|
||||||
|
|
||||||
void *mmapPtr = nullptr;
|
void *mmapPtr = nullptr;
|
||||||
size_t mmapSize = 0u;
|
size_t mmapSize = 0u;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "shared/source/helpers/ptr_math.h"
|
#include "shared/source/helpers/ptr_math.h"
|
||||||
#include "shared/source/helpers/string.h"
|
#include "shared/source/helpers/string.h"
|
||||||
#include "shared/source/helpers/surface_format_info.h"
|
#include "shared/source/helpers/surface_format_info.h"
|
||||||
|
#include "shared/source/memory_manager/allocation_properties.h"
|
||||||
#include "shared/source/memory_manager/host_ptr_manager.h"
|
#include "shared/source/memory_manager/host_ptr_manager.h"
|
||||||
#include "shared/source/memory_manager/memory_banks.h"
|
#include "shared/source/memory_manager/memory_banks.h"
|
||||||
#include "shared/source/memory_manager/memory_pool.h"
|
#include "shared/source/memory_manager/memory_pool.h"
|
||||||
@@ -654,6 +655,101 @@ BufferObject *DrmMemoryManager::findAndReferenceSharedBufferObject(int boHandle,
|
|||||||
return bo;
|
return bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
||||||
|
BufferObjects bos;
|
||||||
|
std::vector<size_t> sizes;
|
||||||
|
size_t totalSize = 0;
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lock(mtx);
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
if (handles.size() != 1) {
|
||||||
|
properties.multiStorageResource = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &drm = this->getDrm(properties.rootDeviceIndex);
|
||||||
|
|
||||||
|
bool areBosSharedObjects = true;
|
||||||
|
|
||||||
|
for (auto handle : handles) {
|
||||||
|
drm_prime_handle openFd = {0, 0, 0};
|
||||||
|
openFd.fd = handle;
|
||||||
|
|
||||||
|
auto ret = this->getDrm(properties.rootDeviceIndex).ioctl(DRM_IOCTL_PRIME_FD_TO_HANDLE, &openFd);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
[[maybe_unused]] int err = errno;
|
||||||
|
PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(PRIME_FD_TO_HANDLE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto boHandle = openFd.handle;
|
||||||
|
auto bo = findAndReferenceSharedBufferObject(boHandle, properties.rootDeviceIndex);
|
||||||
|
|
||||||
|
if (bo == nullptr) {
|
||||||
|
areBosSharedObjects = false;
|
||||||
|
|
||||||
|
size_t size = lseekFunction(handle, 0, SEEK_END);
|
||||||
|
totalSize += size;
|
||||||
|
|
||||||
|
auto patIndex = drm.getPatIndex(nullptr, properties.allocationType, CacheRegion::Default, CachePolicy::WriteBack, false);
|
||||||
|
|
||||||
|
bo = new (std::nothrow) BufferObject(&drm, patIndex, boHandle, size, maxOsContextCount);
|
||||||
|
bo->setRootDeviceIndex(properties.rootDeviceIndex);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
bos.push_back(bo);
|
||||||
|
sizes.push_back(bo->peekSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto heapIndex = HeapIndex::HEAP_STANDARD2MB;
|
||||||
|
auto gpuRange = acquireGpuRange(totalSize, properties.rootDeviceIndex, heapIndex);
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
AllocationData allocationData;
|
||||||
|
properties.size = totalSize;
|
||||||
|
getAllocationData(allocationData, properties, nullptr, createStorageInfoFromProperties(properties));
|
||||||
|
|
||||||
|
auto drmAllocation = new DrmAllocation(properties.rootDeviceIndex,
|
||||||
|
handles.size(),
|
||||||
|
properties.allocationType,
|
||||||
|
bos,
|
||||||
|
nullptr,
|
||||||
|
gpuRange,
|
||||||
|
totalSize,
|
||||||
|
MemoryPool::LocalMemory);
|
||||||
|
drmAllocation->storageInfo = allocationData.storageInfo;
|
||||||
|
|
||||||
|
auto gmmHelper = executionEnvironment.rootDeviceEnvironments[properties.rootDeviceIndex]->getGmmHelper();
|
||||||
|
for (i = 0u; i < handles.size(); i++) {
|
||||||
|
auto bo = bos[i];
|
||||||
|
StorageInfo limitedStorageInfo = allocationData.storageInfo;
|
||||||
|
limitedStorageInfo.memoryBanks &= (1u << (i % handles.size()));
|
||||||
|
auto gmm = new Gmm(gmmHelper,
|
||||||
|
nullptr,
|
||||||
|
bo->peekSize(),
|
||||||
|
0u,
|
||||||
|
CacheSettingsHelper::getGmmUsageType(drmAllocation->getAllocationType(), false, *gmmHelper->getHardwareInfo()),
|
||||||
|
false,
|
||||||
|
allocationData.storageInfo,
|
||||||
|
true);
|
||||||
|
drmAllocation->setGmm(gmm, i);
|
||||||
|
|
||||||
|
if (areBosSharedObjects == false) {
|
||||||
|
bo->setAddress(gpuRange);
|
||||||
|
gpuRange += bo->peekSize();
|
||||||
|
bo->setUnmapSize(sizes[i]);
|
||||||
|
pushSharedBufferObject(bo);
|
||||||
|
}
|
||||||
|
drmAllocation->getBufferObjectToModify(i) = bo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return drmAllocation;
|
||||||
|
}
|
||||||
|
|
||||||
GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
||||||
if (isHostIpcAllocation) {
|
if (isHostIpcAllocation) {
|
||||||
return createUSMHostAllocationFromSharedHandle(handle, properties, false);
|
return createUSMHostAllocationFromSharedHandle(handle, properties, false);
|
||||||
@@ -1468,6 +1564,7 @@ bool DrmMemoryManager::createDrmAllocation(Drm *drm, DrmAllocation *allocation,
|
|||||||
allocation->resizeBufferObjects(handles);
|
allocation->resizeBufferObjects(handles);
|
||||||
bos.resize(handles);
|
bos.resize(handles);
|
||||||
}
|
}
|
||||||
|
allocation->setNumHandles(handles);
|
||||||
|
|
||||||
for (auto handleId = 0u; handleId < handles; handleId++, currentBank++) {
|
for (auto handleId = 0u; handleId < handles; handleId++, currentBank++) {
|
||||||
if (currentBank == banksCnt) {
|
if (currentBank == banksCnt) {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class DrmMemoryManager : public MemoryManager {
|
|||||||
void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation, bool isImportedAllocation) override;
|
void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation, bool isImportedAllocation) override;
|
||||||
void handleFenceCompletion(GraphicsAllocation *allocation) override;
|
void handleFenceCompletion(GraphicsAllocation *allocation) override;
|
||||||
GraphicsAllocation *createGraphicsAllocationFromExistingStorage(AllocationProperties &properties, void *ptr, MultiGraphicsAllocation &multiGraphicsAllocation) override;
|
GraphicsAllocation *createGraphicsAllocationFromExistingStorage(AllocationProperties &properties, void *ptr, MultiGraphicsAllocation &multiGraphicsAllocation) override;
|
||||||
|
GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
||||||
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
||||||
void closeSharedHandle(GraphicsAllocation *gfxAllocation) override;
|
void closeSharedHandle(GraphicsAllocation *gfxAllocation) override;
|
||||||
GraphicsAllocation *createPaddedAllocation(GraphicsAllocation *inputGraphicsAllocation, size_t sizeWithPadding) override;
|
GraphicsAllocation *createPaddedAllocation(GraphicsAllocation *inputGraphicsAllocation, size_t sizeWithPadding) override;
|
||||||
@@ -88,7 +89,7 @@ class DrmMemoryManager : public MemoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BufferObject *findAndReferenceSharedBufferObject(int boHandle, uint32_t rootDeviceIndex);
|
MOCKABLE_VIRTUAL BufferObject *findAndReferenceSharedBufferObject(int boHandle, uint32_t rootDeviceIndex);
|
||||||
void eraseSharedBufferObject(BufferObject *bo);
|
void eraseSharedBufferObject(BufferObject *bo);
|
||||||
void pushSharedBufferObject(BufferObject *bo);
|
void pushSharedBufferObject(BufferObject *bo);
|
||||||
BufferObject *allocUserptr(uintptr_t address, size_t size, uint64_t flags, uint32_t rootDeviceIndex);
|
BufferObject *allocUserptr(uintptr_t address, size_t size, uint64_t flags, uint32_t rootDeviceIndex);
|
||||||
|
|||||||
@@ -451,6 +451,10 @@ GraphicsAllocation *WddmMemoryManager::createAllocationFromHandle(osHandle handl
|
|||||||
return allocation.release();
|
return allocation.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsAllocation *WddmMemoryManager::createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
GraphicsAllocation *WddmMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
GraphicsAllocation *WddmMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) {
|
||||||
return createAllocationFromHandle(handle, requireSpecificBitness, false, properties.allocationType, properties.rootDeviceIndex);
|
return createAllocationFromHandle(handle, requireSpecificBitness, false, properties.allocationType, properties.rootDeviceIndex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class WddmMemoryManager : public MemoryManager {
|
|||||||
void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation, bool isImportedAllocation) override;
|
void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation, bool isImportedAllocation) override;
|
||||||
void handleFenceCompletion(GraphicsAllocation *allocation) override;
|
void handleFenceCompletion(GraphicsAllocation *allocation) override;
|
||||||
|
|
||||||
|
GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
||||||
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override;
|
||||||
GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override;
|
GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override;
|
||||||
|
|
||||||
|
|||||||
@@ -62,3 +62,41 @@ class MemoryAllocatorMultiDeviceFixture : public MemoryManagementFixture, public
|
|||||||
DebugManagerStateRestore restorer;
|
DebugManagerStateRestore restorer;
|
||||||
bool isOsAgnosticMemoryManager;
|
bool isOsAgnosticMemoryManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <uint32_t numRootDevices, uint32_t numSubDevices>
|
||||||
|
class MemoryAllocatorMultiDeviceAndMultiTileFixture : public MemoryManagementFixture, public MemoryAllocatorMultiDeviceSystemSpecificFixture, public ::testing::TestWithParam<bool> {
|
||||||
|
public:
|
||||||
|
void SetUp() override {
|
||||||
|
MemoryManagementFixture::SetUp();
|
||||||
|
|
||||||
|
isOsAgnosticMemoryManager = GetParam();
|
||||||
|
DebugManager.flags.CreateMultipleRootDevices.set(numRootDevices);
|
||||||
|
DebugManager.flags.CreateMultipleRootDevices.set(numSubDevices);
|
||||||
|
VariableBackup<UltHwConfig> backup(&ultHwConfig);
|
||||||
|
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
|
||||||
|
ultHwConfig.forceOsAgnosticMemoryManager = isOsAgnosticMemoryManager;
|
||||||
|
|
||||||
|
executionEnvironment = new MockExecutionEnvironment(defaultHwInfo.get(), true, numRootDevices);
|
||||||
|
devices = DeviceFactory::createDevices(*executionEnvironment);
|
||||||
|
memoryManager = executionEnvironment->memoryManager.get();
|
||||||
|
|
||||||
|
if (!isOsAgnosticMemoryManager) {
|
||||||
|
MemoryAllocatorMultiDeviceSystemSpecificFixture::SetUp(*executionEnvironment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override {
|
||||||
|
if (!isOsAgnosticMemoryManager) {
|
||||||
|
MemoryAllocatorMultiDeviceSystemSpecificFixture::TearDown(*executionEnvironment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getNumRootDevices() { return numRootDevices; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<std::unique_ptr<Device>> devices;
|
||||||
|
ExecutionEnvironment *executionEnvironment = nullptr;
|
||||||
|
MemoryManager *memoryManager = nullptr;
|
||||||
|
DebugManagerStateRestore restorer;
|
||||||
|
bool isOsAgnosticMemoryManager;
|
||||||
|
};
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ TestedDrmMemoryManager::TestedDrmMemoryManager(bool enableLocalMemory,
|
|||||||
lseekCalledCount = 0;
|
lseekCalledCount = 0;
|
||||||
closeInputFd = 0;
|
closeInputFd = 0;
|
||||||
closeCalledCount = 0;
|
closeCalledCount = 0;
|
||||||
|
this->executionEnvironment = &executionEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestedDrmMemoryManager::injectPinBB(BufferObject *newPinBB, uint32_t rootDeviceIndex) {
|
void TestedDrmMemoryManager::injectPinBB(BufferObject *newPinBB, uint32_t rootDeviceIndex) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "shared/source/os_interface/linux/drm_memory_manager.h"
|
#include "shared/source/os_interface/linux/drm_memory_manager.h"
|
||||||
#include "shared/test/common/mocks/mock_memory_manager.h"
|
#include "shared/test/common/mocks/mock_memory_manager.h"
|
||||||
|
#include "shared/test/common/os_interface/linux/device_command_stream_fixture.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
@@ -112,6 +113,15 @@ class TestedDrmMemoryManager : public MemoryManagerCreate<DrmMemoryManager> {
|
|||||||
void forceLimitedRangeAllocator(uint64_t range);
|
void forceLimitedRangeAllocator(uint64_t range);
|
||||||
void overrideGfxPartition(GfxPartition *newGfxPartition);
|
void overrideGfxPartition(GfxPartition *newGfxPartition);
|
||||||
|
|
||||||
|
BufferObject *findAndReferenceSharedBufferObject(int boHandle, uint32_t rootDeviceIndex) override {
|
||||||
|
if (failOnfindAndReferenceSharedBufferObject) {
|
||||||
|
DrmMockCustom drmMock(*executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]);
|
||||||
|
auto patIndex = drmMock.getPatIndex(nullptr, AllocationType::BUFFER, CacheRegion::Default, CachePolicy::WriteBack, false);
|
||||||
|
return new (std::nothrow) BufferObject(&drmMock, patIndex, boHandle, 4096u, 2u);
|
||||||
|
}
|
||||||
|
return MemoryManagerCreate<DrmMemoryManager>::findAndReferenceSharedBufferObject(boHandle, rootDeviceIndex);
|
||||||
|
}
|
||||||
|
|
||||||
DrmAllocation *allocate32BitGraphicsMemory(uint32_t rootDeviceIndex, size_t size, const void *ptr, AllocationType allocationType);
|
DrmAllocation *allocate32BitGraphicsMemory(uint32_t rootDeviceIndex, size_t size, const void *ptr, AllocationType allocationType);
|
||||||
~TestedDrmMemoryManager() override;
|
~TestedDrmMemoryManager() override;
|
||||||
size_t peekSharedBosSize() {
|
size_t peekSharedBosSize() {
|
||||||
@@ -153,6 +163,10 @@ class TestedDrmMemoryManager : public MemoryManagerCreate<DrmMemoryManager> {
|
|||||||
uint32_t alignedFreeWrapperCalled = 0u;
|
uint32_t alignedFreeWrapperCalled = 0u;
|
||||||
uint32_t callsToCloseSharedHandle = 0;
|
uint32_t callsToCloseSharedHandle = 0;
|
||||||
|
|
||||||
|
bool failOnfindAndReferenceSharedBufferObject = false;
|
||||||
|
|
||||||
|
ExecutionEnvironment *executionEnvironment = nullptr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::mutex unreferenceMtx;
|
std::mutex unreferenceMtx;
|
||||||
std::mutex releaseGpuRangeMtx;
|
std::mutex releaseGpuRangeMtx;
|
||||||
|
|||||||
@@ -302,6 +302,10 @@ class FailMemoryManager : public MockMemoryManager {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override {
|
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ int DrmMockCustom::ioctl(unsigned long request, void *arg) {
|
|||||||
primeToHandleParams->handle = outputHandle;
|
primeToHandleParams->handle = outputHandle;
|
||||||
inputFd = primeToHandleParams->fd;
|
inputFd = primeToHandleParams->fd;
|
||||||
ioctl_cnt.primeFdToHandle++;
|
ioctl_cnt.primeFdToHandle++;
|
||||||
|
if (failOnPrimeFdToHandle == true) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case DRM_IOCTL_PRIME_HANDLE_TO_FD: {
|
case DRM_IOCTL_PRIME_HANDLE_TO_FD: {
|
||||||
auto *handleToPrimeParams = (drm_prime_handle *)arg;
|
auto *handleToPrimeParams = (drm_prime_handle *)arg;
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ class DrmMockCustom : public Drm {
|
|||||||
__u64 mmapOffsetExpected = 0;
|
__u64 mmapOffsetExpected = 0;
|
||||||
__u64 mmapOffsetFlags = 0;
|
__u64 mmapOffsetFlags = 0;
|
||||||
bool failOnMmapOffset = false;
|
bool failOnMmapOffset = false;
|
||||||
|
bool failOnPrimeFdToHandle = false;
|
||||||
|
|
||||||
int errnoValue = 0;
|
int errnoValue = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -282,6 +282,7 @@ TEST_F(DeviceGetCapsTest, givenFlagEnabled64kbPagesWhenCallConstructorMemoryMana
|
|||||||
MockMemoryManager(ExecutionEnvironment &executionEnvironment) : MemoryManager(executionEnvironment) {}
|
MockMemoryManager(ExecutionEnvironment &executionEnvironment) : MemoryManager(executionEnvironment) {}
|
||||||
void addAllocationToHostPtrManager(GraphicsAllocation *memory) override{};
|
void addAllocationToHostPtrManager(GraphicsAllocation *memory) override{};
|
||||||
void removeAllocationFromHostPtrManager(GraphicsAllocation *memory) override{};
|
void removeAllocationFromHostPtrManager(GraphicsAllocation *memory) override{};
|
||||||
|
GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(std::vector<osHandle> handles, AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; }
|
||||||
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; };
|
GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; };
|
||||||
GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override { return nullptr; };
|
GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override { return nullptr; };
|
||||||
AllocationStatus populateOsHandles(OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override { return AllocationStatus::Success; };
|
AllocationStatus populateOsHandles(OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override { return AllocationStatus::Success; };
|
||||||
|
|||||||
@@ -216,6 +216,17 @@ TEST(GraphicsAllocationTest, givenDefaultGraphicsAllocationWhenInternalHandleIsB
|
|||||||
EXPECT_EQ(0llu, graphicsAllocation.peekInternalHandle(nullptr));
|
EXPECT_EQ(0llu, graphicsAllocation.peekInternalHandle(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(GraphicsAllocationTest, givenDefaultGraphicsAllocationWhenGettingNumHandlesThenZeroIsReturned) {
|
||||||
|
MockGraphicsAllocation graphicsAllocation;
|
||||||
|
EXPECT_EQ(0u, graphicsAllocation.getNumHandles());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GraphicsAllocationTest, givenDefaultGraphicsAllocationWhenGettingNumHandlesAfterSettingNonZeroNumberThenZeroIsReturned) {
|
||||||
|
MockGraphicsAllocation graphicsAllocation;
|
||||||
|
graphicsAllocation.setNumHandles(64u);
|
||||||
|
EXPECT_EQ(0u, graphicsAllocation.getNumHandles());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(GraphicsAllocationTest, givenGraphicsAllocationWhenQueryingUsedPageSizeThenCorrectSizeForMemoryPoolUsedIsReturned) {
|
TEST(GraphicsAllocationTest, givenGraphicsAllocationWhenQueryingUsedPageSizeThenCorrectSizeForMemoryPoolUsedIsReturned) {
|
||||||
|
|
||||||
MemoryPool::Type page4kPools[] = {MemoryPool::MemoryNull,
|
MemoryPool::Type page4kPools[] = {MemoryPool::MemoryNull,
|
||||||
|
|||||||
Reference in New Issue
Block a user