From 3d9a180c1245a0852d32b8d41a7e2f3c14824f98 Mon Sep 17 00:00:00 2001 From: Krzysztof Gibala Date: Wed, 4 Nov 2020 16:50:54 +0100 Subject: [PATCH] Implement local memory path for all devices in buffer Related-To: NEO-4589 Signed-off-by: Krzysztof Gibala --- .../command_queue/enqueue_read_buffer.h | 3 + .../command_queue/enqueue_write_buffer.h | 5 +- opencl/source/mem_obj/buffer.cpp | 5 +- opencl/source/mem_obj/mem_obj.h | 1 + .../fixtures/multi_root_device_fixture.h | 2 +- .../test/unit_test/mem_obj/buffer_tests.cpp | 52 +++++++++++++ opencl/test/unit_test/mocks/mock_context.cpp | 5 +- opencl/test/unit_test/mocks/mock_context.h | 3 +- .../multi_graphics_allocation.cpp | 40 ++++++++++ .../multi_graphics_allocation.h | 13 ++++ .../multi_graphics_allocation_tests.cpp | 77 ++++++++++++++++++- 11 files changed, 197 insertions(+), 9 deletions(-) diff --git a/opencl/source/command_queue/enqueue_read_buffer.h b/opencl/source/command_queue/enqueue_read_buffer.h index bd7f0dc695..032a9a8688 100644 --- a/opencl/source/command_queue/enqueue_read_buffer.h +++ b/opencl/source/command_queue/enqueue_read_buffer.h @@ -44,6 +44,9 @@ cl_int CommandQueueHw::enqueueReadBuffer( } auto rootDeviceIndex = getDevice().getRootDeviceIndex(); + + buffer->getMigrateableMultiGraphicsAllocation().ensureMemoryOnDevice(*getDevice().getMemoryManager(), rootDeviceIndex); + bool isMemTransferNeeded = buffer->isMemObjZeroCopy() ? buffer->checkIfMemoryTransferIsRequired(offset, 0, ptr, cmdType) : true; bool isCpuCopyAllowed = bufferCpuCopyAllowed(buffer, cmdType, blockingRead, size, ptr, numEventsInWaitList, eventWaitList); diff --git a/opencl/source/command_queue/enqueue_write_buffer.h b/opencl/source/command_queue/enqueue_write_buffer.h index 852bc53c5f..993615506f 100644 --- a/opencl/source/command_queue/enqueue_write_buffer.h +++ b/opencl/source/command_queue/enqueue_write_buffer.h @@ -32,6 +32,10 @@ cl_int CommandQueueHw::enqueueWriteBuffer( const cl_event *eventWaitList, cl_event *event) { + auto rootDeviceIndex = getDevice().getRootDeviceIndex(); + + buffer->getMigrateableMultiGraphicsAllocation().ensureMemoryOnDevice(*getDevice().getMemoryManager(), rootDeviceIndex); + const cl_command_type cmdType = CL_COMMAND_WRITE_BUFFER; auto isMemTransferNeeded = buffer->isMemObjZeroCopy() ? buffer->checkIfMemoryTransferIsRequired(offset, 0, ptr, cmdType) : true; bool isCpuCopyAllowed = bufferCpuCopyAllowed(buffer, cmdType, blockingWrite, size, const_cast(ptr), @@ -39,7 +43,6 @@ cl_int CommandQueueHw::enqueueWriteBuffer( //check if we are dealing with SVM pointer here for which we already have an allocation if (!mapAllocation && this->getContext().getSVMAllocsManager()) { - auto rootDeviceIndex = getDevice().getRootDeviceIndex(); auto svmEntry = this->getContext().getSVMAllocsManager()->getSVMAlloc(ptr); if (svmEntry) { if ((svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex)->getGpuAddress() + svmEntry->size) < (castToUint64(ptr) + size)) { diff --git a/opencl/source/mem_obj/buffer.cpp b/opencl/source/mem_obj/buffer.cpp index 0cfabeb88f..a645173849 100644 --- a/opencl/source/mem_obj/buffer.cpp +++ b/opencl/source/mem_obj/buffer.cpp @@ -178,6 +178,7 @@ Buffer *Buffer::create(Context *context, void *ptr = nullptr; bool forceCopyHostPtr = false; + bool copyExecuted = false; for (auto &rootDeviceIndex : context->getRootDeviceIndices()) { allocationInfo[rootDeviceIndex] = {}; @@ -375,7 +376,7 @@ Buffer *Buffer::create(Context *context, } pBuffer->setHostPtrMinSize(size); - if (allocationInfo[rootDeviceIndex].copyMemoryFromHostPtr) { + if (allocationInfo[rootDeviceIndex].copyMemoryFromHostPtr && !copyExecuted) { auto gmm = allocationInfo[rootDeviceIndex].memory->getDefaultGmm(); bool gpuCopyRequired = (gmm && gmm->isRenderCompressed) || !MemoryPool::isSystemMemoryPool(allocationInfo[rootDeviceIndex].memory->getMemoryPool()); @@ -388,8 +389,10 @@ Buffer *Buffer::create(Context *context, errcodeRet = CL_OUT_OF_RESOURCES; } } + copyExecuted = true; } else { memcpy_s(allocationInfo[rootDeviceIndex].memory->getUnderlyingBuffer(), size, hostPtr, size); + copyExecuted = true; } } } diff --git a/opencl/source/mem_obj/mem_obj.h b/opencl/source/mem_obj/mem_obj.h index bd5cfba6ba..1829fd72f1 100644 --- a/opencl/source/mem_obj/mem_obj.h +++ b/opencl/source/mem_obj/mem_obj.h @@ -131,6 +131,7 @@ class MemObj : public BaseObject<_cl_mem> { const cl_mem_flags &getFlags() const { return flags; } const cl_mem_flags &getFlagsIntel() const { return flagsIntel; } const MultiGraphicsAllocation &getMultiGraphicsAllocation() const { return multiGraphicsAllocation; } + MultiGraphicsAllocation &getMigrateableMultiGraphicsAllocation() { return multiGraphicsAllocation; } protected: void getOsSpecificMemObjectInfo(const cl_mem_info ¶mName, size_t *srcParamSize, void **srcParam); diff --git a/opencl/test/unit_test/fixtures/multi_root_device_fixture.h b/opencl/test/unit_test/fixtures/multi_root_device_fixture.h index 30bb3dfd4b..fb6a2500d0 100644 --- a/opencl/test/unit_test/fixtures/multi_root_device_fixture.h +++ b/opencl/test/unit_test/fixtures/multi_root_device_fixture.h @@ -25,7 +25,7 @@ class MultiRootDeviceFixture : public ::testing::Test { cl_device_id devices[] = { device.get(), device2.get()}; - context.reset(new MockContext(ClDeviceVector(devices, 2))); + context.reset(new MockContext(ClDeviceVector(devices, 2), false)); mockMemoryManager = reinterpret_cast(device->getMemoryManager()); } diff --git a/opencl/test/unit_test/mem_obj/buffer_tests.cpp b/opencl/test/unit_test/mem_obj/buffer_tests.cpp index 8bb5757297..13654dacad 100644 --- a/opencl/test/unit_test/mem_obj/buffer_tests.cpp +++ b/opencl/test/unit_test/mem_obj/buffer_tests.cpp @@ -1830,6 +1830,58 @@ TEST_F(MultiRootDeviceBufferTest, WhenBufferIsCreatedThenBufferGraphicsAllocatio EXPECT_EQ(expectedRootDeviceIndex, graphicsAllocation->getRootDeviceIndex()); } +TEST_F(MultiRootDeviceBufferTest, WhenBufferIsCreatedAndEnqueueWriteCalledThenBufferMultiGraphicsAllocationLastUsedRootDeviceIndexHasCorrectRootDeviceIndex) { + cl_int retVal = 0; + cl_mem_flags flags = CL_MEM_READ_WRITE; + + std::unique_ptr buffer(Buffer::create(context.get(), flags, MemoryConstants::pageSize, nullptr, retVal)); + void *ptr = buffer->getCpuAddressForMemoryTransfer(); + + auto cmdQ1 = context->getSpecialQueue(1u); + cmdQ1->enqueueWriteBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 1u); + + cmdQ1->enqueueWriteBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 1u); + + auto cmdQ2 = context->getSpecialQueue(2u); + cmdQ2->enqueueWriteBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 2u); + + cmdQ1->enqueueWriteBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 1u); + + static_cast(buffer->getMigrateableMultiGraphicsAllocation().getGraphicsAllocation(2u))->overrideMemoryPool(MemoryPool::LocalMemory); + cmdQ2->enqueueWriteBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 2u); +} + +TEST_F(MultiRootDeviceBufferTest, WhenBufferIsCreatedAndEnqueueReadCalledThenBufferMultiGraphicsAllocationLastUsedRootDeviceIndexHasCorrectRootDeviceIndex) { + cl_int retVal = 0; + cl_mem_flags flags = CL_MEM_READ_WRITE; + + std::unique_ptr buffer(Buffer::create(context.get(), flags, MemoryConstants::pageSize, nullptr, retVal)); + void *ptr = buffer->getCpuAddressForMemoryTransfer(); + + auto cmdQ1 = context->getSpecialQueue(1u); + cmdQ1->enqueueReadBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 1u); + + cmdQ1->enqueueReadBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 1u); + + auto cmdQ2 = context->getSpecialQueue(2u); + cmdQ2->enqueueReadBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 2u); + + cmdQ1->enqueueReadBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 1u); + + static_cast(buffer->getMigrateableMultiGraphicsAllocation().getGraphicsAllocation(2u))->overrideMemoryPool(MemoryPool::LocalMemory); + cmdQ2->enqueueReadBuffer(buffer.get(), CL_FALSE, 0, MemoryConstants::pageSize, ptr, nullptr, 0, nullptr, nullptr); + EXPECT_EQ(buffer->getMultiGraphicsAllocation().getLastUsedRootDeviceIndex(), 2u); +} + TEST_F(MultiRootDeviceBufferTest, givenBufferWhenGetSurfaceSizeCalledWithoutAlignSizeForAuxTranslationThenCorrectValueReturned) { cl_int retVal = 0; cl_mem_flags flags = CL_MEM_READ_WRITE; diff --git a/opencl/test/unit_test/mocks/mock_context.cpp b/opencl/test/unit_test/mocks/mock_context.cpp index 1161618daf..0d849fffc7 100644 --- a/opencl/test/unit_test/mocks/mock_context.cpp +++ b/opencl/test/unit_test/mocks/mock_context.cpp @@ -27,8 +27,8 @@ MockContext::MockContext(ClDevice *pDevice, bool noSpecialQueue) { initializeWithDevices(ClDeviceVector{&deviceId, 1}, noSpecialQueue); } -MockContext::MockContext(const ClDeviceVector &clDeviceVector) { - initializeWithDevices(clDeviceVector, true); +MockContext::MockContext(const ClDeviceVector &clDeviceVector, bool noSpecialQueue) { + initializeWithDevices(clDeviceVector, noSpecialQueue); } MockContext::MockContext( @@ -40,7 +40,6 @@ MockContext::MockContext( contextCallback = funcNotify; userData = data; memoryManager = nullptr; - StackVec specialQueues; defaultDeviceQueue = nullptr; driverDiagnostics = nullptr; rootDeviceIndices = {}; diff --git a/opencl/test/unit_test/mocks/mock_context.h b/opencl/test/unit_test/mocks/mock_context.h index 6c0b065c94..cf1bfd0373 100644 --- a/opencl/test/unit_test/mocks/mock_context.h +++ b/opencl/test/unit_test/mocks/mock_context.h @@ -28,10 +28,11 @@ class MockContext : public Context { using Context::rootDeviceIndices; using Context::setupContextType; using Context::sharingFunctions; + using Context::specialQueues; using Context::svmAllocsManager; MockContext(ClDevice *pDevice, bool noSpecialQueue = false); - MockContext(const ClDeviceVector &clDeviceVector); + MockContext(const ClDeviceVector &clDeviceVector, bool noSpecialQueue = true); MockContext( void(CL_CALLBACK *funcNotify)(const char *, const void *, size_t, void *), void *data); diff --git a/shared/source/memory_manager/multi_graphics_allocation.cpp b/shared/source/memory_manager/multi_graphics_allocation.cpp index f3c6c6a4df..a6fd9e9787 100644 --- a/shared/source/memory_manager/multi_graphics_allocation.cpp +++ b/shared/source/memory_manager/multi_graphics_allocation.cpp @@ -7,12 +7,21 @@ #include "shared/source/memory_manager/multi_graphics_allocation.h" +#include "shared/source/helpers/string.h" +#include "shared/source/memory_manager/memory_manager.h" + namespace NEO { MultiGraphicsAllocation::MultiGraphicsAllocation(uint32_t maxRootDeviceIndex) { graphicsAllocations.resize(maxRootDeviceIndex + 1); } +MultiGraphicsAllocation::MultiGraphicsAllocation(const MultiGraphicsAllocation &obj) { + lastUsedRootDeviceIndex = obj.lastUsedRootDeviceIndex; + requiredRootDeviceIndex = obj.requiredRootDeviceIndex; + graphicsAllocations = obj.graphicsAllocations; +} + GraphicsAllocation *MultiGraphicsAllocation::getDefaultGraphicsAllocation() const { for (auto &allocation : graphicsAllocations) { if (allocation) { @@ -48,4 +57,35 @@ StackVec const &MultiGraphicsAllocation::getGraphicsAll return graphicsAllocations; } +void MultiGraphicsAllocation::ensureMemoryOnDevice(MemoryManager &memoryManager, uint32_t requiredRootDeviceIndex) { + std::unique_lock lock(transferMutex); + this->requiredRootDeviceIndex = requiredRootDeviceIndex; + + if (lastUsedRootDeviceIndex == std::numeric_limits::max()) { + lastUsedRootDeviceIndex = requiredRootDeviceIndex; + return; + } + + if (this->requiredRootDeviceIndex == lastUsedRootDeviceIndex) { + return; + } + + if (MemoryPool::isSystemMemoryPool(getGraphicsAllocation(requiredRootDeviceIndex)->getMemoryPool())) { + lastUsedRootDeviceIndex = requiredRootDeviceIndex; + return; + } + + auto srcPtr = memoryManager.lockResource(getGraphicsAllocation(lastUsedRootDeviceIndex)); + auto dstPtr = memoryManager.lockResource(getGraphicsAllocation(requiredRootDeviceIndex)); + + memcpy_s(dstPtr, getGraphicsAllocation(requiredRootDeviceIndex)->getUnderlyingBufferSize(), + srcPtr, getGraphicsAllocation(lastUsedRootDeviceIndex)->getUnderlyingBufferSize()); + + memoryManager.unlockResource(getGraphicsAllocation(lastUsedRootDeviceIndex)); + memoryManager.unlockResource(getGraphicsAllocation(requiredRootDeviceIndex)); + + lastUsedRootDeviceIndex = requiredRootDeviceIndex; + lock.unlock(); +} + } // namespace NEO diff --git a/shared/source/memory_manager/multi_graphics_allocation.h b/shared/source/memory_manager/multi_graphics_allocation.h index 3a0e4d1f05..f71ff9f26b 100644 --- a/shared/source/memory_manager/multi_graphics_allocation.h +++ b/shared/source/memory_manager/multi_graphics_allocation.h @@ -8,12 +8,16 @@ #pragma once #include "shared/source/memory_manager/graphics_allocation.h" +#include + namespace NEO { class MultiGraphicsAllocation { public: MultiGraphicsAllocation(uint32_t maxRootDeviceIndex); + MultiGraphicsAllocation(const MultiGraphicsAllocation &obj); + GraphicsAllocation *getDefaultGraphicsAllocation() const; void addAllocation(GraphicsAllocation *graphicsAllocation); @@ -28,8 +32,17 @@ class MultiGraphicsAllocation { StackVec const &getGraphicsAllocations() const; + void ensureMemoryOnDevice(MemoryManager &memoryManager, uint32_t requiredRootDeviceIndex); + + uint32_t getLastUsedRootDeviceIndex() const { return lastUsedRootDeviceIndex; } + protected: StackVec graphicsAllocations; + + uint32_t lastUsedRootDeviceIndex = std::numeric_limits::max(); + uint32_t requiredRootDeviceIndex = std::numeric_limits::max(); + + std::mutex transferMutex; }; } // namespace NEO diff --git a/shared/test/unit_test/memory_manager/multi_graphics_allocation_tests.cpp b/shared/test/unit_test/memory_manager/multi_graphics_allocation_tests.cpp index 053b637f6c..4eb7a803e8 100644 --- a/shared/test/unit_test/memory_manager/multi_graphics_allocation_tests.cpp +++ b/shared/test/unit_test/memory_manager/multi_graphics_allocation_tests.cpp @@ -5,14 +5,18 @@ * */ +#include "shared/source/helpers/aligned_memory.h" #include "shared/source/memory_manager/multi_graphics_allocation.h" +#include "opencl/test/unit_test/mocks/mock_memory_manager.h" + #include "gtest/gtest.h" using namespace NEO; struct MockMultiGraphicsAllocation : public MultiGraphicsAllocation { using MultiGraphicsAllocation::graphicsAllocations; + using MultiGraphicsAllocation::lastUsedRootDeviceIndex; using MultiGraphicsAllocation::MultiGraphicsAllocation; }; @@ -84,7 +88,7 @@ TEST(MultiGraphicsAllocationTest, WhenCreatingMultiGraphicsAllocationWithoutGrap EXPECT_EQ(nullptr, multiGraphicsAllocation.getDefaultGraphicsAllocation()); } -TEST(MultiGraphicsAllocationTest, givenMultiGraphicsAllocationwhenRemovingGraphicsAllocationThenTheAllocationIsNoLongerAvailable) { +TEST(MultiGraphicsAllocationTest, givenMultiGraphicsAllocationWhenRemovingGraphicsAllocationThenTheAllocationIsNoLongerAvailable) { uint32_t rootDeviceIndex = 1u; GraphicsAllocation graphicsAllocation(rootDeviceIndex, GraphicsAllocation::AllocationType::BUFFER, @@ -100,4 +104,73 @@ TEST(MultiGraphicsAllocationTest, givenMultiGraphicsAllocationwhenRemovingGraphi multiGraphicsAllocation.removeAllocation(rootDeviceIndex); EXPECT_EQ(nullptr, multiGraphicsAllocation.getGraphicsAllocation(rootDeviceIndex)); -} \ No newline at end of file +} + +TEST(MultiGraphicsAllocationTest, givenMultiGraphicsAllocationWhenEnsureMemoryOnDeviceIsCalledThenDataIsProperlyTransferred) { + constexpr auto bufferSize = 4u; + + uint8_t hostBuffer[bufferSize] = {1u, 1u, 1u, 1u}; + uint8_t refBuffer[bufferSize] = {3u, 3u, 3u, 3u}; + + GraphicsAllocation graphicsAllocation1(1u, GraphicsAllocation::AllocationType::BUFFER, hostBuffer, bufferSize, 0, MemoryPool::LocalMemory, 0); + GraphicsAllocation graphicsAllocation2(2u, GraphicsAllocation::AllocationType::BUFFER, refBuffer, bufferSize, 0, MemoryPool::LocalMemory, 0); + + MockMultiGraphicsAllocation multiGraphicsAllocation(2u); + multiGraphicsAllocation.addAllocation(&graphicsAllocation1); + multiGraphicsAllocation.addAllocation(&graphicsAllocation2); + + MockExecutionEnvironment mockExecutionEnvironment(defaultHwInfo.get()); + MockMemoryManager mockMemoryManager(mockExecutionEnvironment); + + multiGraphicsAllocation.lastUsedRootDeviceIndex = 1u; + multiGraphicsAllocation.ensureMemoryOnDevice(mockMemoryManager, 2u); + + auto underlyingBuffer1 = multiGraphicsAllocation.getGraphicsAllocation(1u)->getUnderlyingBuffer(); + auto ptrUnderlyingBuffer1 = static_cast(underlyingBuffer1); + + auto underlyingBuffer2 = multiGraphicsAllocation.getGraphicsAllocation(2u)->getUnderlyingBuffer(); + auto ptrUnderlyingBuffer2 = static_cast(underlyingBuffer2); + + for (auto i = 0u; i < bufferSize; i++) { + EXPECT_EQ(ptrUnderlyingBuffer1[i], ptrUnderlyingBuffer2[i]); + } +} + +TEST(MultiGraphicsAllocationTest, givenMultiGraphicsAllocationWhenEnsureMemoryOnDeviceIsCalledThenLockAndUnlockAreProperlyCalled) { + constexpr auto bufferSize = 4u; + + uint8_t hostBuffer[bufferSize] = {1u, 1u, 1u, 1u}; + uint8_t refBuffer[bufferSize] = {3u, 3u, 3u, 3u}; + + MemoryAllocation allocation1(1u, GraphicsAllocation::AllocationType::BUFFER, hostBuffer, bufferSize, 0, MemoryPool::System4KBPages, 0); + MemoryAllocation allocation2(2u, GraphicsAllocation::AllocationType::BUFFER, refBuffer, bufferSize, 0, MemoryPool::System4KBPages, 0); + + MockMultiGraphicsAllocation multiGraphicsAllocation(2u); + multiGraphicsAllocation.addAllocation(&allocation1); + multiGraphicsAllocation.addAllocation(&allocation2); + + MockExecutionEnvironment mockExecutionEnvironment(defaultHwInfo.get()); + MockMemoryManager mockMemoryManager(mockExecutionEnvironment); + + multiGraphicsAllocation.ensureMemoryOnDevice(mockMemoryManager, 1u); + EXPECT_EQ(mockMemoryManager.lockResourceCalled, 0u); + EXPECT_EQ(mockMemoryManager.unlockResourceCalled, 0u); + + multiGraphicsAllocation.ensureMemoryOnDevice(mockMemoryManager, 1u); + EXPECT_EQ(mockMemoryManager.lockResourceCalled, 0u); + EXPECT_EQ(mockMemoryManager.unlockResourceCalled, 0u); + + multiGraphicsAllocation.ensureMemoryOnDevice(mockMemoryManager, 2u); + EXPECT_EQ(mockMemoryManager.lockResourceCalled, 0u); + EXPECT_EQ(mockMemoryManager.unlockResourceCalled, 0u); + + multiGraphicsAllocation.ensureMemoryOnDevice(mockMemoryManager, 1u); + EXPECT_EQ(mockMemoryManager.lockResourceCalled, 0u); + EXPECT_EQ(mockMemoryManager.unlockResourceCalled, 0u); + + (&allocation1)->overrideMemoryPool(MemoryPool::LocalMemory); + (&allocation2)->overrideMemoryPool(MemoryPool::LocalMemory); + multiGraphicsAllocation.ensureMemoryOnDevice(mockMemoryManager, 2u); + EXPECT_EQ(mockMemoryManager.lockResourceCalled, 2u); + EXPECT_EQ(mockMemoryManager.unlockResourceCalled, 2u); +}