diff --git a/runtime/os_interface/linux/drm_buffer_object.cpp b/runtime/os_interface/linux/drm_buffer_object.cpp index d0441082bb..a83f7de02f 100644 --- a/runtime/os_interface/linux/drm_buffer_object.cpp +++ b/runtime/os_interface/linux/drm_buffer_object.cpp @@ -29,7 +29,7 @@ namespace OCLRT { -BufferObject::BufferObject(Drm *drm, int handle, bool isAllocated) : isResident(false), drm(drm), refCount(1), handle(handle), isReused(false), isAllocated(isAllocated) { +BufferObject::BufferObject(Drm *drm, int handle, bool isAllocated) : drm(drm), refCount(1), handle(handle), isReused(false), isAllocated(isAllocated) { this->isSoftpin = false; this->tiling_mode = I915_TILING_NONE; diff --git a/runtime/os_interface/linux/drm_buffer_object.h b/runtime/os_interface/linux/drm_buffer_object.h index 93f90af09f..a27f2f87c1 100644 --- a/runtime/os_interface/linux/drm_buffer_object.h +++ b/runtime/os_interface/linux/drm_buffer_object.h @@ -73,11 +73,9 @@ class BufferObject { ResidencyVector *getResidency() { return &residency; } StorageAllocatorType peekAllocationType() const { return storageAllocatorType; } void setAllocationType(StorageAllocatorType allocatorType) { this->storageAllocatorType = allocatorType; } - bool peekIsResident() const { return isResident; } - void setIsResident(bool isResident) { this->isResident = isResident; } + bool peekIsReusableAllocation() { return this->isReused; } protected: - bool isResident; BufferObject(Drm *drm, int handle, bool isAllocated); Drm *drm; diff --git a/runtime/os_interface/linux/drm_command_stream.inl b/runtime/os_interface/linux/drm_command_stream.inl index 44389173ad..70d7c2a5c3 100644 --- a/runtime/os_interface/linux/drm_command_stream.inl +++ b/runtime/os_interface/linux/drm_command_stream.inl @@ -71,9 +71,6 @@ FlushStamp DrmCommandStreamReceiver::flush(BatchBuffer &batchBuffer, batchBuffer.requiresCoherency, batchBuffer.low_priority); - for (auto &surface : *(bb->getResidency())) { - surface->setIsResident(false); - } bb->getResidency()->clear(); if (this->gemCloseWorkerOperationMode == gemCloseWorkerActive) { @@ -96,8 +93,15 @@ void DrmCommandStreamReceiver::makeResident(GraphicsAllocation &gfxAl template void DrmCommandStreamReceiver::makeResident(BufferObject *bo) { - if (bo && !bo->peekIsResident()) { - bo->setIsResident(true); + if (bo) { + if (bo->peekIsReusableAllocation()) { + for (auto bufferObject : this->residency) { + if (bufferObject == bo) { + return; + } + } + } + residency.push_back(bo); } } @@ -108,8 +112,10 @@ void DrmCommandStreamReceiver::processResidency(ResidencyContainer &i auto drmAlloc = static_cast(alloc); if (drmAlloc->fragmentsStorage.fragmentCount) { for (unsigned int f = 0; f < drmAlloc->fragmentsStorage.fragmentCount; f++) { - makeResident(drmAlloc->fragmentsStorage.fragmentStorageData[f].osHandleStorage->bo); - drmAlloc->fragmentsStorage.fragmentStorageData[f].residency->resident = true; + if (!drmAlloc->fragmentsStorage.fragmentStorageData[f].residency->resident) { + makeResident(drmAlloc->fragmentsStorage.fragmentStorageData[f].osHandleStorage->bo); + drmAlloc->fragmentsStorage.fragmentStorageData[f].residency->resident = true; + } } } else { BufferObject *bo = drmAlloc->getBO(); @@ -124,15 +130,11 @@ void DrmCommandStreamReceiver::makeNonResident(GraphicsAllocation &gf // If flush wasn't called we need to make all objects non-resident. // If makeNonResident is called before flush, vector will be cleared. if (gfxAllocation.residencyTaskCount[this->deviceIndex] != ObjectNotResident) { - for (auto &surface : residency) { - surface->setIsResident(false); - } if (this->residency.size() != 0) { this->residency.clear(); } if (gfxAllocation.fragmentsStorage.fragmentCount) { for (auto fragmentId = 0u; fragmentId < gfxAllocation.fragmentsStorage.fragmentCount; fragmentId++) { - gfxAllocation.fragmentsStorage.fragmentStorageData[fragmentId].osHandleStorage->bo->setIsResident(false); gfxAllocation.fragmentsStorage.fragmentStorageData[fragmentId].residency->resident = false; } } diff --git a/unit_tests/mocks/CMakeLists.txt b/unit_tests/mocks/CMakeLists.txt index a548ecb5c0..29e2141012 100644 --- a/unit_tests/mocks/CMakeLists.txt +++ b/unit_tests/mocks/CMakeLists.txt @@ -82,6 +82,7 @@ if(WIN32) else() list(APPEND IGDRCL_SRCS_tests_mocks ${CMAKE_CURRENT_SOURCE_DIR}/linux/mock_drm_memory_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/linux/mock_drm_command_stream_receiver.h ) endif() diff --git a/unit_tests/mocks/linux/mock_drm_command_stream_receiver.h b/unit_tests/mocks/linux/mock_drm_command_stream_receiver.h new file mode 100644 index 0000000000..901d533e01 --- /dev/null +++ b/unit_tests/mocks/linux/mock_drm_command_stream_receiver.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2018 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +template +class TestedDrmCommandStreamReceiver : public DrmCommandStreamReceiver { + public: + using CommandStreamReceiver::commandStream; + using DrmCommandStreamReceiver::residency; + + TestedDrmCommandStreamReceiver(gemCloseWorkerMode mode, ExecutionEnvironment &executionEnvironment) + : DrmCommandStreamReceiver(*platformDevices[0], executionEnvironment, mode) { + } + TestedDrmCommandStreamReceiver(ExecutionEnvironment &executionEnvironment) + : DrmCommandStreamReceiver(*platformDevices[0], executionEnvironment, + gemCloseWorkerMode::gemCloseWorkerInactive) { + } + + void overrideGemCloseWorkerOperationMode(gemCloseWorkerMode overrideValue) { + this->gemCloseWorkerOperationMode = overrideValue; + } + + void overrideDispatchPolicy(DispatchMode overrideValue) { + this->dispatchMode = overrideValue; + } + + bool isResident(BufferObject *bo) { + bool resident = false; + for (auto it : this->residency) { + if (it == bo) { + resident = true; + break; + } + } + return resident; + } + + void makeNonResident(GraphicsAllocation &gfxAllocation) override { + makeNonResidentResult.called = true; + makeNonResidentResult.allocation = &gfxAllocation; + DrmCommandStreamReceiver::makeNonResident(gfxAllocation); + } + + const BufferObject *getResident(BufferObject *bo) { + BufferObject *ret = nullptr; + for (auto it : this->residency) { + if (it == bo) { + ret = it; + break; + } + } + return ret; + } + + struct MakeResidentNonResidentResult { + bool called; + GraphicsAllocation *allocation; + }; + + MakeResidentNonResidentResult makeNonResidentResult; + std::vector *getResidencyVector() { return &this->residency; } + + SubmissionAggregator *peekSubmissionAggregator() { + return this->submissionAggregator.get(); + } + void overrideSubmissionAggregator(SubmissionAggregator *newSubmissionsAggregator) { + this->submissionAggregator.reset(newSubmissionsAggregator); + } + std::vector &getExecStorage() { + return this->execObjectsStorage; + } +}; diff --git a/unit_tests/os_interface/linux/drm_command_stream_tests.cpp b/unit_tests/os_interface/linux/drm_command_stream_tests.cpp index 4fdaecc00c..ae8aecbc39 100644 --- a/unit_tests/os_interface/linux/drm_command_stream_tests.cpp +++ b/unit_tests/os_interface/linux/drm_command_stream_tests.cpp @@ -17,6 +17,7 @@ #include "unit_tests/helpers/debug_manager_state_restore.h" #include "unit_tests/helpers/execution_environment_helper.h" #include "unit_tests/helpers/hw_parse.h" +#include "unit_tests/mocks/linux/mock_drm_command_stream_receiver.h" #include "unit_tests/mocks/mock_program.h" #include "unit_tests/mocks/mock_host_ptr_manager.h" #include "unit_tests/mocks/mock_submissions_aggregator.h" @@ -688,7 +689,7 @@ class DrmCommandStreamEnhancedFixture } bool isResident(BufferObject *bo) { - return tCsr->isResident(bo) && bo->peekIsResident(); + return tCsr->isResident(bo); } const BufferObject *getResident(BufferObject *bo) { @@ -696,73 +697,6 @@ class DrmCommandStreamEnhancedFixture } protected: - template - class TestedDrmCommandStreamReceiver : public DrmCommandStreamReceiver { - public: - using CommandStreamReceiver::commandStream; - - TestedDrmCommandStreamReceiver(gemCloseWorkerMode mode, ExecutionEnvironment &executionEnvironment) - : DrmCommandStreamReceiver(*platformDevices[0], executionEnvironment, mode) { - } - TestedDrmCommandStreamReceiver(ExecutionEnvironment &executionEnvironment) - : DrmCommandStreamReceiver(*platformDevices[0], executionEnvironment, - gemCloseWorkerMode::gemCloseWorkerInactive) { - } - - void overrideGemCloseWorkerOperationMode(gemCloseWorkerMode overrideValue) { - this->gemCloseWorkerOperationMode = overrideValue; - } - - void overrideDispatchPolicy(DispatchMode overrideValue) { - this->dispatchMode = overrideValue; - } - - bool isResident(BufferObject *bo) { - bool resident = false; - for (auto it : this->residency) { - if (it == bo) { - resident = true; - break; - } - } - return resident; - } - - void makeNonResident(GraphicsAllocation &gfxAllocation) override { - makeNonResidentResult.called = true; - makeNonResidentResult.allocation = &gfxAllocation; - DrmCommandStreamReceiver::makeNonResident(gfxAllocation); - } - - const BufferObject *getResident(BufferObject *bo) { - BufferObject *ret = nullptr; - for (auto it : this->residency) { - if (it == bo) { - ret = it; - break; - } - } - return ret; - } - - struct MakeResidentNonResidentResult { - bool called; - GraphicsAllocation *allocation; - }; - - MakeResidentNonResidentResult makeNonResidentResult; - std::vector *getResidencyVector() { return &this->residency; } - - SubmissionAggregator *peekSubmissionAggregator() { - return this->submissionAggregator.get(); - } - void overrideSubmissionAggregator(SubmissionAggregator *newSubmissionsAggregator) { - this->submissionAggregator.reset(newSubmissionsAggregator); - } - std::vector &getExecStorage() { - return this->execObjectsStorage; - } - }; TestedDrmCommandStreamReceiver *tCsr = nullptr; class MockBufferObject : public BufferObject { @@ -779,6 +713,7 @@ class DrmCommandStreamEnhancedFixture return new MockBufferObject(this->mock, size); } }; + typedef Test DrmCommandStreamGemWorkerTests; TEST_F(DrmCommandStreamGemWorkerTests, givenDefaultDrmCSRWhenItIsCreatedThenGemCloseWorkerModeIsInactive) { @@ -835,8 +770,6 @@ TEST_F(DrmCommandStreamGemWorkerTests, givenTaskThatRequiresLargeResourceCountWh EXPECT_EQ(11u, this->mock->execBuffer.buffer_count); mm->freeGraphicsMemory(commandBuffer); for (auto graphicsAllocation : graphicsAllocations) { - DrmAllocation *drmAlloc = static_cast(graphicsAllocation); - EXPECT_FALSE(drmAlloc->getBO()->peekIsResident()); mm->freeGraphicsMemory(graphicsAllocation); } EXPECT_EQ(11u, execStorage.size()); @@ -863,24 +796,24 @@ TEST_F(DrmCommandStreamGemWorkerTests, GivenTwoAllocationsWhenBackingStorageIsDi auto allocation = static_cast(mm->allocateGraphicsMemory(1024)); auto allocation2 = static_cast(mm->allocateGraphicsMemory(1024)); - auto bo1 = allocation->getBO(); - auto bo2 = allocation2->getBO(); csr->makeResident(*allocation); csr->makeResident(*allocation2); - EXPECT_FALSE(bo1->peekIsResident()); - EXPECT_FALSE(bo2->peekIsResident()); + EXPECT_TRUE(allocation->isResident(0u)); + EXPECT_TRUE(allocation2->isResident(0u)); csr->processResidency(csr->getResidencyAllocations(), *osContext); - EXPECT_TRUE(bo1->peekIsResident()); - EXPECT_TRUE(bo2->peekIsResident()); + EXPECT_TRUE(allocation->isResident(0u)); + EXPECT_TRUE(allocation2->isResident(0u)); + EXPECT_EQ(tCsr->getResidencyVector()->size(), 2u); csr->makeNonResident(*allocation); csr->makeNonResident(*allocation2); - EXPECT_FALSE(bo1->peekIsResident()); - EXPECT_FALSE(bo2->peekIsResident()); + + EXPECT_FALSE(allocation->isResident(0u)); + EXPECT_FALSE(allocation2->isResident(0u)); EXPECT_EQ(tCsr->getResidencyVector()->size(), 0u); mm->freeGraphicsMemory(allocation); diff --git a/unit_tests/os_interface/linux/drm_memory_manager_tests.cpp b/unit_tests/os_interface/linux/drm_memory_manager_tests.cpp index cf4340d28b..43298558e7 100644 --- a/unit_tests/os_interface/linux/drm_memory_manager_tests.cpp +++ b/unit_tests/os_interface/linux/drm_memory_manager_tests.cpp @@ -20,7 +20,9 @@ #include "runtime/os_interface/linux/drm_buffer_object.h" #include "runtime/os_interface/linux/drm_command_stream.h" #include "runtime/os_interface/linux/drm_memory_manager.h" +#include "runtime/os_interface/linux/os_interface.h" #include "runtime/os_interface/32bit_memory.h" +#include "runtime/os_interface/os_context.h" #include "runtime/utilities/tag_allocator.h" #include "unit_tests/fixtures/memory_management_fixture.h" @@ -30,6 +32,7 @@ #include "unit_tests/mocks/mock_context.h" #include "unit_tests/mocks/mock_device.h" #include "unit_tests/mocks/mock_gmm.h" +#include "unit_tests/mocks/linux/mock_drm_command_stream_receiver.h" #include "unit_tests/mocks/linux/mock_drm_memory_manager.h" #include "unit_tests/os_interface/linux/device_command_stream_fixture.h" @@ -1557,6 +1560,61 @@ TEST_F(DrmMemoryManagerTest, givenSharedHandleWhenAllocationIsCreatedAndIoctlPri memoryManager->freeGraphicsMemory(graphicsAllocation); } +TEST_F(DrmMemoryManagerTest, givenTwoGraphicsAllocationsThatShareTheSameBufferObjectWhenTheyAreMadeResidentThenOnlyOneBoIsPassedToExec) { + mock->ioctl_expected.primeFdToHandle = 2; + mock->ioctl_expected.gemClose = 1; + mock->ioctl_expected.gemWait = 2; + + osHandle sharedHandle = 1u; + auto graphicsAllocation = memoryManager->createGraphicsAllocationFromSharedHandle(sharedHandle, false); + auto graphicsAllocation2 = memoryManager->createGraphicsAllocationFromSharedHandle(sharedHandle, false); + + executionEnvironment->osInterface = std::make_unique(); + executionEnvironment->osInterface->get()->setDrm(mock); + auto testedCsr = new TestedDrmCommandStreamReceiver(*executionEnvironment); + executionEnvironment->commandStreamReceivers.push_back(std::unique_ptr(testedCsr)); + + testedCsr->makeResident(*graphicsAllocation); + testedCsr->makeResident(*graphicsAllocation2); + EXPECT_EQ(2u, testedCsr->getResidencyAllocations().size()); + + OsContext osContext(executionEnvironment->osInterface.get(), 0u); + testedCsr->processResidency(testedCsr->getResidencyAllocations(), osContext); + + EXPECT_EQ(1u, testedCsr->residency.size()); + + memoryManager->freeGraphicsMemory(graphicsAllocation); + memoryManager->freeGraphicsMemory(graphicsAllocation2); +} + +TEST_F(DrmMemoryManagerTest, givenTwoGraphicsAllocationsThatDoesnShareTheSameBufferObjectWhenTheyAreMadeResidentThenTwoBoIsPassedToExec) { + mock->ioctl_expected.primeFdToHandle = 2; + mock->ioctl_expected.gemClose = 2; + mock->ioctl_expected.gemWait = 2; + + osHandle sharedHandle = 1u; + auto graphicsAllocation = memoryManager->createGraphicsAllocationFromSharedHandle(sharedHandle, false); + mock->outputHandle++; + auto graphicsAllocation2 = memoryManager->createGraphicsAllocationFromSharedHandle(sharedHandle, false); + + executionEnvironment->osInterface = std::make_unique(); + executionEnvironment->osInterface->get()->setDrm(mock); + auto testedCsr = new TestedDrmCommandStreamReceiver(*executionEnvironment); + executionEnvironment->commandStreamReceivers.push_back(std::unique_ptr(testedCsr)); + + testedCsr->makeResident(*graphicsAllocation); + testedCsr->makeResident(*graphicsAllocation2); + EXPECT_EQ(2u, testedCsr->getResidencyAllocations().size()); + + OsContext osContext(executionEnvironment->osInterface.get(), 0u); + testedCsr->processResidency(testedCsr->getResidencyAllocations(), osContext); + + EXPECT_EQ(2u, testedCsr->residency.size()); + + memoryManager->freeGraphicsMemory(graphicsAllocation); + memoryManager->freeGraphicsMemory(graphicsAllocation2); +} + TEST_F(DrmMemoryManagerWithExplicitExpectationsTest, givenDrmMemoryManagerWhenCreateAllocationFromNtHandleIsCalledThenReturnNullptr) { auto graphicsAllocation = memoryManager->createGraphicsAllocationFromNTHandle(reinterpret_cast(1)); EXPECT_EQ(nullptr, graphicsAllocation); @@ -1808,6 +1866,7 @@ TEST_F(DrmMemoryManagerTest, givenSharedAllocationWithSmallerThenRealSizeWhenCre EXPECT_EQ(1, lseekCalledCount); memoryManager->freeGraphicsMemory(graphicsAllocation); } + TEST_F(DrmMemoryManagerTest, givenMemoryManagerSupportingVirutalPaddingWhenItIsRequiredThenNewGraphicsAllocationIsCreated) { mock->ioctl_expected.gemUserptr = 3; mock->ioctl_expected.gemWait = 3;