Reuse graphics allocation from mapped buffers in OpenCL

Related-To: NEO-6352
Signed-off-by: Maciej Dziuban <maciej.dziuban@intel.com>
This commit is contained in:
Maciej Dziuban 2021-10-18 15:07:01 +00:00 committed by Compute-Runtime-Automation
parent f164acad0b
commit f1b6b733f0
21 changed files with 376 additions and 54 deletions

View File

@ -428,7 +428,8 @@ void *CommandQueue::enqueueReadMemObjForMap(TransferProperties &transferProperti
void *returnPtr = ptrOffset(basePtr, mapPtrOffset);
if (!transferProperties.memObj->addMappedPtr(returnPtr, transferProperties.memObj->calculateMappedPtrLength(transferProperties.size),
transferProperties.mapFlags, transferProperties.size, transferProperties.offset, transferProperties.mipLevel)) {
transferProperties.mapFlags, transferProperties.size, transferProperties.offset, transferProperties.mipLevel,
transferProperties.memObj->getMapAllocation(getDevice().getRootDeviceIndex()))) {
errcodeRet = CL_INVALID_OPERATION;
return nullptr;
}

View File

@ -32,7 +32,7 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie
transferProperties.memObj->calculateOffsetForMapping(transferProperties.offset) + transferProperties.mipPtrOffset);
if (!transferProperties.memObj->addMappedPtr(returnPtr, transferProperties.memObj->calculateMappedPtrLength(transferProperties.size),
transferProperties.mapFlags, transferProperties.size, transferProperties.offset, transferProperties.mipLevel)) {
transferProperties.mapFlags, transferProperties.size, transferProperties.offset, transferProperties.mipLevel, nullptr)) {
err.set(CL_INVALID_OPERATION);
return nullptr;
}

View File

@ -48,22 +48,12 @@ cl_int CommandQueueHw<GfxFamily>::enqueueReadBuffer(
bool isMemTransferNeeded = buffer->isMemObjZeroCopy() ? buffer->checkIfMemoryTransferIsRequired(offset, 0, ptr, cmdType) : true;
bool isCpuCopyAllowed = bufferCpuCopyAllowed(buffer, cmdType, blockingRead, size, ptr,
numEventsInWaitList, eventWaitList);
InternalMemoryType memoryType = InternalMemoryType::NOT_SPECIFIED;
//check if we are dealing with SVM pointer here for which we already have an allocation
if (!mapAllocation && this->getContext().getSVMAllocsManager()) {
auto svmEntry = this->getContext().getSVMAllocsManager()->getSVMAlloc(ptr);
if (svmEntry) {
memoryType = svmEntry->memoryType;
if ((svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex)->getGpuAddress() + svmEntry->size) < (castToUint64(ptr) + size)) {
return CL_INVALID_OPERATION;
}
mapAllocation = svmEntry->cpuAllocation ? svmEntry->cpuAllocation : svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex);
if (isCpuCopyAllowed) {
if (svmEntry->memoryType == DEVICE_UNIFIED_MEMORY) {
isCpuCopyAllowed = false;
}
}
if (!mapAllocation) {
cl_int retVal = getContext().tryGetExistingHostPtrAllocation(ptr, size, rootDeviceIndex, mapAllocation, memoryType, isCpuCopyAllowed);
if (retVal != CL_SUCCESS) {
return retVal;
}
}

View File

@ -40,23 +40,12 @@ cl_int CommandQueueHw<GfxFamily>::enqueueWriteBuffer(
auto isMemTransferNeeded = buffer->isMemObjZeroCopy() ? buffer->checkIfMemoryTransferIsRequired(offset, 0, ptr, cmdType) : true;
bool isCpuCopyAllowed = bufferCpuCopyAllowed(buffer, cmdType, blockingWrite, size, const_cast<void *>(ptr),
numEventsInWaitList, eventWaitList);
InternalMemoryType memoryType = InternalMemoryType::NOT_SPECIFIED;
//check if we are dealing with SVM pointer here for which we already have an allocation
if (!mapAllocation && this->getContext().getSVMAllocsManager()) {
auto svmEntry = this->getContext().getSVMAllocsManager()->getSVMAlloc(ptr);
if (svmEntry) {
memoryType = svmEntry->memoryType;
if ((svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex)->getGpuAddress() + svmEntry->size) < (castToUint64(ptr) + size)) {
return CL_INVALID_OPERATION;
}
if (isCpuCopyAllowed) {
if (svmEntry->memoryType == DEVICE_UNIFIED_MEMORY) {
isCpuCopyAllowed = false;
}
}
mapAllocation = svmEntry->cpuAllocation ? svmEntry->cpuAllocation : svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex);
if (!mapAllocation) {
cl_int retVal = getContext().tryGetExistingHostPtrAllocation(ptr, size, rootDeviceIndex, mapAllocation, memoryType, isCpuCopyAllowed);
if (retVal != CL_SUCCESS) {
return retVal;
}
}

View File

@ -82,6 +82,38 @@ cl_int Context::setDestructorCallback(void(CL_CALLBACK *funcNotify)(cl_context,
return CL_SUCCESS;
}
cl_int Context::tryGetExistingHostPtrAllocation(const void *ptr,
size_t size,
uint32_t rootDeviceIndex,
GraphicsAllocation *&allocation,
InternalMemoryType &memoryType,
bool &isCpuCopyAllowed) {
if (getSVMAllocsManager()) {
SvmAllocationData *svmEntry = getSVMAllocsManager()->getSVMAlloc(ptr);
if (svmEntry) {
memoryType = svmEntry->memoryType;
if ((svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex)->getGpuAddress() + svmEntry->size) < (castToUint64(ptr) + size)) {
return CL_INVALID_OPERATION;
}
allocation = svmEntry->cpuAllocation ? svmEntry->cpuAllocation : svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex);
if (isCpuCopyAllowed) {
if (svmEntry->memoryType == DEVICE_UNIFIED_MEMORY) {
isCpuCopyAllowed = false;
}
}
return CL_SUCCESS;
}
}
if (MapInfo mapInfo = {}; mapOperationsStorage.getInfoForHostPtr(ptr, size, mapInfo)) {
if (mapInfo.graphicsAllocation) {
allocation = mapInfo.graphicsAllocation;
}
}
return CL_SUCCESS;
}
const std::set<uint32_t> &Context::getRootDeviceIndices() const {
return rootDeviceIndices;
}

View File

@ -9,6 +9,7 @@
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/helpers/common_types.h"
#include "shared/source/helpers/vec.h"
#include "shared/source/unified_memory/unified_memory.h"
#include "opencl/source/cl_device/cl_device_vector.h"
#include "opencl/source/context/context_type.h"
@ -96,6 +97,13 @@ class Context : public BaseObject<_cl_context> {
auto &getMapOperationsStorage() { return mapOperationsStorage; }
cl_int tryGetExistingHostPtrAllocation(const void *ptr,
size_t size,
uint32_t rootDeviceIndex,
GraphicsAllocation *&allocation,
InternalMemoryType &memoryType,
bool &isCpuCopyAllowed);
const std::set<uint32_t> &getRootDeviceIndices() const;
uint32_t getMaxRootDeviceIndex() const;

View File

@ -17,6 +17,7 @@
namespace NEO {
class MemObj;
class Buffer;
class GraphicsAllocation;
struct EventsRequest {
EventsRequest() = delete;
@ -69,5 +70,6 @@ struct MapInfo {
void *ptr = nullptr;
uint32_t mipLevel = 0;
bool readOnly = false;
GraphicsAllocation *graphicsAllocation = nullptr;
};
} // namespace NEO

View File

@ -16,10 +16,11 @@ size_t MapOperationsHandler::size() const {
return mappedPointers.size();
}
bool MapOperationsHandler::add(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset, uint32_t mipLevel) {
bool MapOperationsHandler::add(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset, uint32_t mipLevel, GraphicsAllocation *graphicsAllocation) {
std::lock_guard<std::mutex> lock(mtx);
MapInfo mapInfo(ptr, ptrLength, size, offset, mipLevel);
mapInfo.readOnly = (mapFlags == CL_MAP_READ);
mapInfo.graphicsAllocation = graphicsAllocation;
if (isOverlapping(mapInfo)) {
return false;
@ -60,6 +61,19 @@ bool MapOperationsHandler::find(void *mappedPtr, MapInfo &outMapInfo) {
return false;
}
bool NEO::MapOperationsHandler::findInfoForHostPtr(const void *ptr, size_t size, MapInfo &outMapInfo) {
for (auto &mapInfo : mappedPointers) {
void *ptrStart = mapInfo.ptr;
void *ptrEnd = ptrOffset(mapInfo.ptr, mapInfo.ptrLength);
if (ptrStart <= ptr && ptrOffset(ptr, size) <= ptrEnd) {
outMapInfo = mapInfo;
return true;
}
}
return false;
}
void MapOperationsHandler::remove(void *mappedPtr) {
std::lock_guard<std::mutex> lock(mtx);
@ -88,6 +102,15 @@ MapOperationsHandler *NEO::MapOperationsStorage::getHandlerIfExists(cl_mem memOb
return &iterator->second;
}
bool NEO::MapOperationsStorage::getInfoForHostPtr(const void *ptr, size_t size, MapInfo &outInfo) {
for (auto &entry : handlers) {
if (entry.second.findInfoForHostPtr(ptr, size, outInfo)) {
return true;
}
}
return false;
}
void NEO::MapOperationsStorage::removeHandler(cl_mem memObj) {
std::lock_guard<std::mutex> lock(mutex);
auto iterator = handlers.find(memObj);

View File

@ -18,9 +18,10 @@ class MapOperationsHandler {
public:
virtual ~MapOperationsHandler() = default;
bool add(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset, uint32_t mipLevel);
bool add(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset, uint32_t mipLevel, GraphicsAllocation *graphicsAllocation);
void remove(void *mappedPtr);
bool find(void *mappedPtr, MapInfo &outMapInfo);
bool findInfoForHostPtr(const void *ptr, size_t size, MapInfo &outMapInfo);
size_t size() const;
protected:
@ -35,6 +36,7 @@ class MapOperationsStorage {
MapOperationsHandler &getHandler(cl_mem memObj);
MapOperationsHandler *getHandlerIfExists(cl_mem memObj);
bool getInfoForHostPtr(const void *ptr, size_t size, MapInfo &outInfo);
void removeHandler(cl_mem memObj);
protected:

View File

@ -397,8 +397,8 @@ MapOperationsHandler *MemObj::getMapOperationsHandlerIfExists() {
bool MemObj::addMappedPtr(void *ptr, size_t ptrLength, cl_map_flags &mapFlags,
MemObjSizeArray &size, MemObjOffsetArray &offset,
uint32_t mipLevel) {
return getMapOperationsHandler().add(ptr, ptrLength, mapFlags, size, offset, mipLevel);
uint32_t mipLevel, GraphicsAllocation *graphicsAllocation) {
return getMapOperationsHandler().add(ptr, ptrLength, mapFlags, size, offset, mipLevel, graphicsAllocation);
}
bool MemObj::findMappedPtr(void *mappedPtr, MapInfo &outMapInfo) {

View File

@ -88,7 +88,7 @@ class MemObj : public BaseObject<_cl_mem> {
MapOperationsHandler &getMapOperationsHandler();
MapOperationsHandler *getMapOperationsHandlerIfExists();
bool addMappedPtr(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset, uint32_t mipLevel);
bool addMappedPtr(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset, uint32_t mipLevel, GraphicsAllocation *graphicsAllocation);
bool findMappedPtr(void *mappedPtr, MapInfo &outMapInfo);
void removeMappedPtr(void *mappedPtr);
void *getBasePtrForMap(uint32_t rootDeviceIndex);

View File

@ -9,6 +9,7 @@
#include "shared/source/device/device.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/mocks/mock_gmm.h"
#include "opencl/source/command_queue/command_queue_hw.h"
#include "opencl/source/context/context.h"
@ -57,6 +58,15 @@ CommandQueue *CommandQueueHwFixture::createCommandQueue(
return funcCreate(pContext, pDevice, properties, false);
}
void CommandQueueHwFixture::forceMapBufferOnGpu(Buffer &buffer) {
ClDevice *clDevice = buffer.getContext()->getDevice(0);
buffer.setSharingHandler(new SharingHandler());
auto gfxAllocation = buffer.getGraphicsAllocation(clDevice->getRootDeviceIndex());
for (auto handleId = 0u; handleId < gfxAllocation->getNumGmms(); handleId++) {
gfxAllocation->setGmm(new MockGmm(clDevice->getGmmClientContext()), handleId);
}
}
void CommandQueueHwFixture::SetUp() {
ASSERT_NE(nullptr, pCmdQ);
context = new MockContext();

View File

@ -33,6 +33,8 @@ struct CommandQueueHwFixture {
const cl_command_queue_properties *properties,
Context *context);
static void forceMapBufferOnGpu(Buffer &buffer);
virtual void SetUp();
virtual void SetUp(ClDevice *pDevice, cl_command_queue_properties properties);

View File

@ -747,3 +747,27 @@ TEST_F(EnqueueMapBufferTest, givenBufferWithUseHostPtrFlagWhenMappedOnCpuThenSet
EXPECT_EQ(mappedPtr, expectedPtr);
}
HWTEST_F(EnqueueMapBufferTest, givenMapBufferOnGpuWhenMappingBufferThenStoreGraphicsAllocationInMapInfo) {
uint8_t hostPtr[10] = {};
std::unique_ptr<Buffer> bufferForCpuMap(Buffer::create(context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, 10, hostPtr, retVal));
ASSERT_NE(nullptr, bufferForCpuMap);
ASSERT_TRUE(bufferForCpuMap->mappingOnCpuAllowed());
std::unique_ptr<Buffer> bufferForGpuMap(Buffer::create(context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, 10, hostPtr, retVal));
ASSERT_NE(nullptr, bufferForGpuMap);
forceMapBufferOnGpu(*bufferForGpuMap);
ASSERT_FALSE(bufferForGpuMap->mappingOnCpuAllowed());
cl_int retVal{};
void *pointerMappedOnCpu = clEnqueueMapBuffer(pCmdQ, bufferForCpuMap.get(), CL_FALSE, CL_MAP_READ, 0, 10, 0, nullptr, nullptr, &retVal);
EXPECT_EQ(CL_SUCCESS, retVal);
void *pointerMappedOnGpu = clEnqueueMapBuffer(pCmdQ, bufferForGpuMap.get(), CL_FALSE, CL_MAP_READ, 0, 10, 0, nullptr, nullptr, &retVal);
EXPECT_EQ(CL_SUCCESS, retVal);
MapInfo mapInfo{};
EXPECT_TRUE(bufferForCpuMap->findMappedPtr(pointerMappedOnCpu, mapInfo));
EXPECT_EQ(nullptr, mapInfo.graphicsAllocation);
EXPECT_TRUE(bufferForGpuMap->findMappedPtr(pointerMappedOnGpu, mapInfo));
EXPECT_NE(nullptr, mapInfo.graphicsAllocation);
}

View File

@ -13,6 +13,7 @@
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/unit_test_helper.h"
#include "shared/test/common/mocks/mock_execution_environment.h"
#include "shared/test/unit_test/utilities/base_object_utils.h"
#include "opencl/source/built_ins/builtins_dispatch_builder.h"
#include "opencl/source/helpers/dispatch_info.h"
@ -750,3 +751,37 @@ HWTEST_F(EnqueueReadBufferStatefulTest, WhenReadingBufferStatefulThenSuccessIsRe
EXPECT_EQ(CL_SUCCESS, retVal);
}
HWTEST_F(EnqueueReadBufferHw, givenHostPtrIsFromMappedBufferWhenReadBufferIsCalledThenReuseGraphicsAllocation) {
DebugManagerStateRestore restore{};
DebugManager.flags.DisableZeroCopyForBuffers.set(1);
DebugManager.flags.DoCpuCopyOnReadBuffer.set(0);
MockCommandQueueHw<FamilyType> queue(context.get(), device.get(), nullptr);
auto &csr = device->getUltCommandStreamReceiver<FamilyType>();
BufferDefaults::context = context.get();
auto bufferForMap = clUniquePtr(BufferHelper<>::create());
auto bufferForRead = clUniquePtr(BufferHelper<>::create());
cl_int retVal{};
void *mappedPtr = queue.enqueueMapBuffer(bufferForMap.get(), CL_TRUE, CL_MAP_READ, 0, bufferForMap->getSize(), 0, nullptr, nullptr, retVal);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_NE(nullptr, mappedPtr);
EXPECT_EQ(0u, csr.createAllocationForHostSurfaceCalled);
MapOperationsHandler *mapOperationsHandler = context->getMapOperationsStorage().getHandlerIfExists(bufferForMap.get());
EXPECT_NE(nullptr, mapOperationsHandler);
MapInfo mapInfo{};
EXPECT_TRUE(mapOperationsHandler->find(mappedPtr, mapInfo));
EXPECT_NE(nullptr, mapInfo.graphicsAllocation);
auto unmappedPtr = std::make_unique<char[]>(bufferForRead->getSize());
retVal = queue.enqueueReadBuffer(bufferForRead.get(), CL_TRUE, 0, bufferForRead->getSize(), unmappedPtr.get(), nullptr, 0, 0, nullptr);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(1u, csr.createAllocationForHostSurfaceCalled);
retVal = queue.enqueueReadBuffer(bufferForRead.get(), CL_TRUE, 0, bufferForRead->getSize(), mappedPtr, nullptr, 0, 0, nullptr);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(1u, csr.createAllocationForHostSurfaceCalled);
}

View File

@ -11,6 +11,7 @@
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/unit_test_helper.h"
#include "shared/test/common/mocks/mock_execution_environment.h"
#include "shared/test/unit_test/utilities/base_object_utils.h"
#include "opencl/source/built_ins/builtins_dispatch_builder.h"
#include "opencl/source/helpers/dispatch_info.h"
@ -563,3 +564,37 @@ HWTEST_F(EnqueueWriteBufferStatefulTest, WhenWritingBufferStatefulThenSuccessIsR
EXPECT_EQ(CL_SUCCESS, retVal);
}
HWTEST_F(EnqueueWriteBufferHw, givenHostPtrIsFromMappedBufferWhenWriteBufferIsCalledThenReuseGraphicsAllocation) {
DebugManagerStateRestore restore{};
DebugManager.flags.DisableZeroCopyForBuffers.set(1);
DebugManager.flags.DoCpuCopyOnWriteBuffer.set(0);
MockCommandQueueHw<FamilyType> queue(context.get(), device.get(), nullptr);
auto &csr = device->getUltCommandStreamReceiver<FamilyType>();
BufferDefaults::context = context.get();
auto bufferForMap = clUniquePtr(BufferHelper<>::create());
auto bufferForRead = clUniquePtr(BufferHelper<>::create());
cl_int retVal{};
void *mappedPtr = queue.enqueueMapBuffer(bufferForMap.get(), CL_TRUE, CL_MAP_READ, 0, bufferForMap->getSize(), 0, nullptr, nullptr, retVal);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_NE(nullptr, mappedPtr);
EXPECT_EQ(0u, csr.createAllocationForHostSurfaceCalled);
MapOperationsHandler *mapOperationsHandler = context->getMapOperationsStorage().getHandlerIfExists(bufferForMap.get());
EXPECT_NE(nullptr, mapOperationsHandler);
MapInfo mapInfo{};
EXPECT_TRUE(mapOperationsHandler->find(mappedPtr, mapInfo));
EXPECT_NE(nullptr, mapInfo.graphicsAllocation);
auto unmappedPtr = std::make_unique<char[]>(bufferForRead->getSize());
retVal = queue.enqueueWriteBuffer(bufferForRead.get(), CL_TRUE, 0, bufferForRead->getSize(), unmappedPtr.get(), nullptr, 0, 0, nullptr);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(1u, csr.createAllocationForHostSurfaceCalled);
retVal = queue.enqueueWriteBuffer(bufferForRead.get(), CL_TRUE, 0, bufferForRead->getSize(), mappedPtr, nullptr, 0, 0, nullptr);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(1u, csr.createAllocationForHostSurfaceCalled);
}

View File

@ -8,6 +8,7 @@
#include "shared/source/device/device.h"
#include "shared/source/helpers/blit_commands_helper.h"
#include "shared/source/helpers/local_memory_access_modes.h"
#include "shared/source/memory_manager/unified_memory_manager.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/variable_backup.h"
#include "shared/test/common/mocks/mock_deferred_deleter.h"
@ -20,6 +21,7 @@
#include "opencl/source/mem_obj/buffer.h"
#include "opencl/source/sharings/sharing.h"
#include "opencl/test/unit_test/fixtures/platform_fixture.h"
#include "opencl/test/unit_test/mocks/mock_buffer.h"
#include "opencl/test/unit_test/mocks/mock_cl_device.h"
#include "opencl/test/unit_test/mocks/mock_command_queue.h"
#include "opencl/test/unit_test/mocks/mock_context.h"
@ -70,6 +72,10 @@ struct ContextTest : public PlatformFixture,
PlatformFixture::TearDown();
}
uint32_t getRootDeviceIndex() {
return context->getDevice(0)->getRootDeviceIndex();
}
cl_int retVal = CL_SUCCESS;
WhiteBoxContext *context = nullptr;
cl_context_properties *properties = nullptr;
@ -567,4 +573,155 @@ HWCMDTEST_F(IGFX_XE_HP_CORE, ContextCreateTests, givenLocalMemoryAllocationWhenB
executionEnv->rootDeviceEnvironments[0]->getMutableHardwareInfo()->capabilityTable.blitterOperationsSupported = true;
EXPECT_EQ(BlitOperationResult::Success, BlitHelper::blitMemoryToAllocation(buffer->getContext()->getDevice(0)->getDevice(), memory, buffer->getOffset(), hostMemory, {1, 1, 1}));
}
}
}
struct AllocationReuseContextTest : ContextTest {
void addMappedPtr(Buffer &buffer, void *ptr, size_t ptrLength) {
auto &handler = context->getMapOperationsStorage().getHandler(&buffer);
MemObjSizeArray size{};
MemObjSizeArray offset{};
cl_map_flags mapFlag = CL_MAP_READ;
EXPECT_TRUE(handler.add(ptr, ptrLength, mapFlag, size, offset, 0, buffer.getMultiGraphicsAllocation().getDefaultGraphicsAllocation()));
}
void addSvmPtr(InternalMemoryType type, GraphicsAllocation &allocation) {
SvmAllocationData svmEntry{getRootDeviceIndex()};
svmEntry.memoryType = type;
svmEntry.size = allocation.getUnderlyingBufferSize();
svmEntry.gpuAllocations.addAllocation(&allocation);
if (type != InternalMemoryType::DEVICE_UNIFIED_MEMORY) {
svmEntry.cpuAllocation = &allocation;
}
context->getSVMAllocsManager()->insertSVMAlloc(svmEntry);
}
};
TEST_F(AllocationReuseContextTest, givenSharedSvmAllocPresentWhenGettingExistingHostPtrAllocThenRetrieveTheAllocation) {
REQUIRE_SVM_OR_SKIP(context->getDevice(0));
uint64_t svmPtrGpu = 0x1234;
void *svmPtr = reinterpret_cast<void *>(svmPtrGpu);
MockGraphicsAllocation allocation{svmPtr, svmPtrGpu, 400};
addSvmPtr(InternalMemoryType::SHARED_UNIFIED_MEMORY, allocation);
GraphicsAllocation *retrievedAllocation{};
InternalMemoryType retrievedMemoryType{};
bool retrievedCpuCopyStatus = true;
retVal = context->tryGetExistingHostPtrAllocation(svmPtr, allocation.getUnderlyingBufferSize(), getRootDeviceIndex(),
retrievedAllocation, retrievedMemoryType, retrievedCpuCopyStatus);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(&allocation, retrievedAllocation);
EXPECT_EQ(InternalMemoryType::SHARED_UNIFIED_MEMORY, retrievedMemoryType);
EXPECT_TRUE(retrievedCpuCopyStatus);
}
TEST_F(AllocationReuseContextTest, givenHostSvmAllocPresentWhenGettingExistingHostPtrAllocThenRetrieveTheAllocation) {
REQUIRE_SVM_OR_SKIP(context->getDevice(0));
uint64_t svmPtrGpu = 0x1234;
void *svmPtr = reinterpret_cast<void *>(svmPtrGpu);
MockGraphicsAllocation allocation{svmPtr, svmPtrGpu, 400};
addSvmPtr(InternalMemoryType::HOST_UNIFIED_MEMORY, allocation);
GraphicsAllocation *retrievedAllocation{};
InternalMemoryType retrievedMemoryType{};
bool retrievedCpuCopyStatus = true;
retVal = context->tryGetExistingHostPtrAllocation(svmPtr, allocation.getUnderlyingBufferSize(), getRootDeviceIndex(),
retrievedAllocation, retrievedMemoryType, retrievedCpuCopyStatus);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(&allocation, retrievedAllocation);
EXPECT_EQ(InternalMemoryType::HOST_UNIFIED_MEMORY, retrievedMemoryType);
EXPECT_TRUE(retrievedCpuCopyStatus);
}
TEST_F(AllocationReuseContextTest, givenDeviceSvmAllocPresentWhenGettingExistingHostPtrAllocThenRetrieveTheAllocationAndDisallowCpuCopy) {
REQUIRE_SVM_OR_SKIP(context->getDevice(0));
uint64_t svmPtrGpu = 0x1234;
void *svmPtr = reinterpret_cast<void *>(svmPtrGpu);
MockGraphicsAllocation allocation{svmPtr, svmPtrGpu, 400};
addSvmPtr(InternalMemoryType::DEVICE_UNIFIED_MEMORY, allocation);
GraphicsAllocation *retrievedAllocation{};
InternalMemoryType retrievedMemoryType{};
bool retrievedCpuCopyStatus = true;
retVal = context->tryGetExistingHostPtrAllocation(svmPtr, allocation.getUnderlyingBufferSize(), getRootDeviceIndex(),
retrievedAllocation, retrievedMemoryType, retrievedCpuCopyStatus);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(&allocation, retrievedAllocation);
EXPECT_EQ(InternalMemoryType::DEVICE_UNIFIED_MEMORY, retrievedMemoryType);
EXPECT_FALSE(retrievedCpuCopyStatus);
}
TEST_F(AllocationReuseContextTest, givenHostSvmAllocPresentButRequestingTooBigSizeWhenGettingExistingHostPtrAllocThenReturnError) {
REQUIRE_SVM_OR_SKIP(context->getDevice(0));
uint64_t svmPtrGpu = 0x1234;
void *svmPtr = reinterpret_cast<void *>(svmPtrGpu);
MockGraphicsAllocation allocation{svmPtr, svmPtrGpu, 400};
addSvmPtr(InternalMemoryType::HOST_UNIFIED_MEMORY, allocation);
size_t ptrSizeToRetrieve = allocation.getUnderlyingBufferSize() + 1;
GraphicsAllocation *retrievedAllocation{};
InternalMemoryType retrievedMemoryType{};
bool retrievedCpuCopyStatus = true;
retVal = context->tryGetExistingHostPtrAllocation(svmPtr, ptrSizeToRetrieve, getRootDeviceIndex(),
retrievedAllocation, retrievedMemoryType, retrievedCpuCopyStatus);
EXPECT_EQ(CL_INVALID_OPERATION, retVal);
}
TEST_F(AllocationReuseContextTest, givenHostPtrStoredInMapOperationsStorageWhenGettingExistingHostPtrAllocThenRetrieveTheAllocation) {
MockGraphicsAllocation allocation{};
MockBuffer buffer{context, allocation};
void *mappedPtr = reinterpret_cast<void *>(0x1234);
size_t mappedPtrSize = 10u;
addMappedPtr(buffer, mappedPtr, mappedPtrSize);
GraphicsAllocation *retrievedAllocation{};
InternalMemoryType retrievedMemoryType{};
bool retrievedCpuCopyStatus = true;
retVal = context->tryGetExistingHostPtrAllocation(mappedPtr, mappedPtrSize, getRootDeviceIndex(),
retrievedAllocation, retrievedMemoryType, retrievedCpuCopyStatus);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(&allocation, retrievedAllocation);
EXPECT_EQ(InternalMemoryType::NOT_SPECIFIED, retrievedMemoryType);
EXPECT_TRUE(retrievedCpuCopyStatus);
}
TEST_F(AllocationReuseContextTest, givenHostPtrNotStoredInMapOperationsStorageWhenGettingExistingHostPtrAllocThenFailToRetrieveTheAllocation) {
MockGraphicsAllocation allocation{};
MockBuffer buffer{context, allocation};
void *mappedPtr = reinterpret_cast<void *>(0x1234);
size_t mappedPtrSize = 10u;
addMappedPtr(buffer, mappedPtr, mappedPtrSize);
void *differentPtr = reinterpret_cast<void *>(0x12345);
GraphicsAllocation *retrievedAllocation{};
InternalMemoryType retrievedMemoryType{};
bool retrievedCpuCopyStatus = true;
retVal = context->tryGetExistingHostPtrAllocation(differentPtr, mappedPtrSize, getRootDeviceIndex(),
retrievedAllocation, retrievedMemoryType, retrievedCpuCopyStatus);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(nullptr, retrievedAllocation);
EXPECT_EQ(InternalMemoryType::NOT_SPECIFIED, retrievedMemoryType);
EXPECT_TRUE(retrievedCpuCopyStatus);
}
TEST_F(AllocationReuseContextTest, givenHostPtrStoredInMapOperationsStorageAndRequestedPtrToBigWhenGettingExistingHostPtrAllocThenFailRetrieveTheAllocation) {
MockGraphicsAllocation allocation{};
MockBuffer buffer{context, allocation};
void *mappedPtr = reinterpret_cast<void *>(0x1234);
size_t mappedPtrSize = 10u;
addMappedPtr(buffer, mappedPtr, mappedPtrSize);
size_t ptrSizeToRetrieve = mappedPtrSize + 1;
GraphicsAllocation *retrievedAllocation{};
InternalMemoryType retrievedMemoryType{};
bool retrievedCpuCopyStatus = true;
retVal = context->tryGetExistingHostPtrAllocation(mappedPtr, ptrSizeToRetrieve, getRootDeviceIndex(),
retrievedAllocation, retrievedMemoryType, retrievedCpuCopyStatus);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(nullptr, retrievedAllocation);
EXPECT_EQ(InternalMemoryType::NOT_SPECIFIED, retrievedMemoryType);
EXPECT_TRUE(retrievedCpuCopyStatus);
}

View File

@ -65,7 +65,7 @@ HWTEST_F(ImageUnmapTest, givenImageWhenUnmapMemObjIsCalledThenEnqueueNonBlocking
MemObjSizeArray region = {{1, 1, 1}};
image->setAllocatedMapPtr(ptr);
cl_map_flags mapFlags = CL_MAP_WRITE;
image->addMappedPtr(ptr, 1, mapFlags, region, origin, 0);
image->addMappedPtr(ptr, 1, mapFlags, region, origin, 0, nullptr);
AllocationProperties properties{0, false, MemoryConstants::cacheLineSize, GraphicsAllocation::AllocationType::MAP_ALLOCATION, false, device->getDeviceBitfield()};
auto allocation = device->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties, ptr);

View File

@ -22,6 +22,11 @@ struct MockMapOperationsHandler : public MapOperationsHandler {
struct MapOperationsHandlerTests : public ::testing::Test {
MockMapOperationsHandler mockHandler;
std::unique_ptr<MockGraphicsAllocation> allocations[3] = {
std::make_unique<MockGraphicsAllocation>(),
std::make_unique<MockGraphicsAllocation>(),
std::make_unique<MockGraphicsAllocation>(),
};
MapInfo mappedPtrs[3] = {
{(void *)0x1000, 1, {{1, 2, 3}}, {{4, 5, 6}}, 0},
{(void *)0x2000, 1, {{7, 8, 9}}, {{10, 11, 12}}, 0},
@ -32,7 +37,7 @@ struct MapOperationsHandlerTests : public ::testing::Test {
TEST_F(MapOperationsHandlerTests, givenMapInfoWhenFindingThenReturnCorrectvalues) {
for (size_t i = 0; i < 3; i++) {
EXPECT_TRUE(mockHandler.add(mappedPtrs[i].ptr, mappedPtrs[i].ptrLength, mapFlags, mappedPtrs[i].size, mappedPtrs[i].offset, 0));
EXPECT_TRUE(mockHandler.add(mappedPtrs[i].ptr, mappedPtrs[i].ptrLength, mapFlags, mappedPtrs[i].size, mappedPtrs[i].offset, 0, allocations[i].get()));
}
EXPECT_EQ(3u, mockHandler.size());
@ -42,12 +47,13 @@ TEST_F(MapOperationsHandlerTests, givenMapInfoWhenFindingThenReturnCorrectvalues
EXPECT_EQ(receivedMapInfo.ptr, mappedPtrs[i].ptr);
EXPECT_EQ(receivedMapInfo.size, mappedPtrs[i].size);
EXPECT_EQ(receivedMapInfo.offset, mappedPtrs[i].offset);
EXPECT_EQ(allocations[i].get(), receivedMapInfo.graphicsAllocation);
}
}
TEST_F(MapOperationsHandlerTests, givenMapInfoWhenRemovingThenRemoveCorrectPointers) {
for (size_t i = 0; i < 3; i++) {
mockHandler.add(mappedPtrs[i].ptr, mappedPtrs[i].ptrLength, mapFlags, mappedPtrs[i].size, mappedPtrs[i].offset, 0);
mockHandler.add(mappedPtrs[i].ptr, mappedPtrs[i].ptrLength, mapFlags, mappedPtrs[i].size, mappedPtrs[i].offset, 0, allocations[i].get());
}
for (int i = 2; i >= 0; i--) {
@ -59,8 +65,8 @@ TEST_F(MapOperationsHandlerTests, givenMapInfoWhenRemovingThenRemoveCorrectPoint
}
TEST_F(MapOperationsHandlerTests, givenMappedPtrsWhenDoubleRemovedThenDoNothing) {
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[1].ptr, mappedPtrs[1].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
mockHandler.add(mappedPtrs[1].ptr, mappedPtrs[1].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[1].get());
EXPECT_EQ(2u, mockHandler.size());
mockHandler.remove(mappedPtrs[1].ptr);
@ -74,27 +80,27 @@ TEST_F(MapOperationsHandlerTests, givenMappedPtrsWhenDoubleRemovedThenDoNothing)
TEST_F(MapOperationsHandlerTests, givenMapInfoWhenAddedThenSetReadOnlyFlag) {
mapFlags = CL_MAP_READ;
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
EXPECT_TRUE(mockHandler.mappedPointers.back().readOnly);
mockHandler.remove(mappedPtrs[0].ptr);
mapFlags = CL_MAP_WRITE;
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly);
mockHandler.remove(mappedPtrs[0].ptr);
mapFlags = CL_MAP_WRITE_INVALIDATE_REGION;
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly);
mockHandler.remove(mappedPtrs[0].ptr);
mapFlags = CL_MAP_READ | CL_MAP_WRITE;
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly);
mockHandler.remove(mappedPtrs[0].ptr);
mapFlags = CL_MAP_READ | CL_MAP_WRITE_INVALIDATE_REGION;
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly);
mockHandler.remove(mappedPtrs[0].ptr);
}
@ -102,24 +108,24 @@ TEST_F(MapOperationsHandlerTests, givenMapInfoWhenAddedThenSetReadOnlyFlag) {
TEST_F(MapOperationsHandlerTests, givenNonReadOnlyOverlappingPtrWhenAddingThenReturnFalseAndDontAdd) {
mapFlags = CL_MAP_WRITE;
mappedPtrs->readOnly = false;
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
EXPECT_EQ(1u, mockHandler.size());
EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly);
EXPECT_TRUE(mockHandler.isOverlapping(mappedPtrs[0]));
EXPECT_FALSE(mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0));
EXPECT_FALSE(mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get()));
EXPECT_EQ(1u, mockHandler.size());
}
TEST_F(MapOperationsHandlerTests, givenReadOnlyOverlappingPtrWhenAddingThenReturnTrueAndAdd) {
mapFlags = CL_MAP_READ;
mappedPtrs->readOnly = true;
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0);
mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get());
EXPECT_EQ(1u, mockHandler.size());
EXPECT_TRUE(mockHandler.mappedPointers.back().readOnly);
EXPECT_FALSE(mockHandler.isOverlapping(mappedPtrs[0]));
EXPECT_TRUE(mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0));
EXPECT_TRUE(mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset, 0, allocations[0].get()));
EXPECT_EQ(2u, mockHandler.size());
EXPECT_TRUE(mockHandler.mappedPointers.back().readOnly);
}
@ -153,7 +159,7 @@ TEST_P(MapOperationsHandlerOverlapTests, givenAlreadyMappedPtrWhenAskingForOverl
requestedInfo.readOnly = false;
MockMapOperationsHandler mockHandler;
mockHandler.add(mappedInfo.ptr, mappedInfo.ptrLength, mapFlags, mappedInfo.size, mappedInfo.offset, 0);
mockHandler.add(mappedInfo.ptr, mappedInfo.ptrLength, mapFlags, mappedInfo.size, mappedInfo.offset, 0, mappedInfo.graphicsAllocation);
EXPECT_EQ(expectOverlap, mockHandler.isOverlapping(requestedInfo));
}

View File

@ -230,7 +230,7 @@ HWTEST_P(MemObjAsyncDestructionTest, givenUsedMemObjWithAsyncDestructionsEnabled
ClMemoryPropertiesHelper::createMemoryProperties(CL_MEM_READ_WRITE, 0, 0, &context->getDevice(0)->getDevice()),
CL_MEM_READ_WRITE, 0, size,
storage, nullptr, GraphicsAllocationHelper::toMultiGraphicsAllocation(allocation), true, false, false);
memObj->addMappedPtr(storage, 1, mapFlags, region, origin, 0);
memObj->addMappedPtr(storage, 1, mapFlags, region, origin, 0, nullptr);
} else {
memObj->setAllocatedMapPtr(storage);
}

View File

@ -279,6 +279,11 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw<GfxFamily>, publ
return blitterDirectSubmissionAvailable;
}
bool createAllocationForHostSurface(HostPtrSurface &surface, bool requiresL3Flush) override {
createAllocationForHostSurfaceCalled++;
return BaseClass::createAllocationForHostSurface(surface, requiresL3Flush);
}
void ensureCommandBufferAllocation(LinearStream &commandStream, size_t minimumRequiredSize, size_t additionalAllocationSize) override {
ensureCommandBufferAllocationCalled++;
BaseClass::ensureCommandBufferAllocation(commandStream, minimumRequiredSize, additionalAllocationSize);
@ -302,6 +307,7 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw<GfxFamily>, publ
int ensureCommandBufferAllocationCalled = 0;
DispatchFlags recordedDispatchFlags;
BlitPropertiesContainer receivedBlitProperties = {};
uint32_t createAllocationForHostSurfaceCalled = 0;
bool createPageTableManagerCalled = false;
bool recordFlusheBatchBuffer = false;