diff --git a/runtime/os_interface/linux/drm_buffer_object.cpp b/runtime/os_interface/linux/drm_buffer_object.cpp index 97c6c11410..c5c24498be 100644 --- a/runtime/os_interface/linux/drm_buffer_object.cpp +++ b/runtime/os_interface/linux/drm_buffer_object.cpp @@ -44,7 +44,7 @@ namespace OCLRT { -BufferObject::BufferObject(Drm *drm, int handle, bool isAllocated) : drm(drm), refCount(1), handle(handle), isReused(false), isAllocated(isAllocated) { +BufferObject::BufferObject(Drm *drm, int handle, bool isAllocated) : isResident(false), 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 851c7fe022..be239dbe47 100644 --- a/runtime/os_interface/linux/drm_buffer_object.h +++ b/runtime/os_interface/linux/drm_buffer_object.h @@ -88,8 +88,11 @@ 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; } protected: + bool isResident; BufferObject(Drm *drm, int handle, bool isAllocated); Drm *drm; @@ -112,11 +115,11 @@ class BufferObject { uint64_t offset64; // last-seen GPU offset size_t size; - void *address; // GPU side virtual address + void *address; // GPU side virtual address void *lockedAddress; // CPU side virtual address bool isAllocated = false; uint64_t unmapSize = 0; StorageAllocatorType storageAllocatorType = UNKNOWN_ALLOCATOR; }; -} +} // namespace OCLRT diff --git a/runtime/os_interface/linux/drm_command_stream.inl b/runtime/os_interface/linux/drm_command_stream.inl index 923201f074..aed2e41dd5 100644 --- a/runtime/os_interface/linux/drm_command_stream.inl +++ b/runtime/os_interface/linux/drm_command_stream.inl @@ -100,7 +100,8 @@ void DrmCommandStreamReceiver::makeResident(GraphicsAllocation &gfxAl template void DrmCommandStreamReceiver::makeResident(BufferObject *bo) { - if (bo) { + if (bo && !bo->peekIsResident()) { + bo->setIsResident(true); residency.push_back(bo); } } @@ -108,14 +109,12 @@ void DrmCommandStreamReceiver::makeResident(BufferObject *bo) { template void DrmCommandStreamReceiver::processResidency(ResidencyContainer *inputAllocationsForResidency) { auto &allocationsForResidency = inputAllocationsForResidency ? *inputAllocationsForResidency : getMemoryManager()->getResidencyAllocations(); - for (uint32_t i = 0; i < allocationsForResidency.size(); i++) { - DrmAllocation *drmAlloc = reinterpret_cast(allocationsForResidency[i]); + for (uint32_t a = 0; a < allocationsForResidency.size(); a++) { + DrmAllocation *drmAlloc = reinterpret_cast(allocationsForResidency[a]); if (drmAlloc->fragmentsStorage.fragmentCount) { - for (unsigned int i = 0; i < drmAlloc->fragmentsStorage.fragmentCount; i++) { - if (!drmAlloc->fragmentsStorage.fragmentStorageData[i].residency->resident) { - makeResident(drmAlloc->fragmentsStorage.fragmentStorageData[i].osHandleStorage->bo); - drmAlloc->fragmentsStorage.fragmentStorageData[i].residency->resident = true; - } + for (unsigned int f = 0; f < drmAlloc->fragmentsStorage.fragmentCount; f++) { + makeResident(drmAlloc->fragmentsStorage.fragmentStorageData[f].osHandleStorage->bo); + drmAlloc->fragmentsStorage.fragmentStorageData[f].residency->resident = true; } } else { BufferObject *bo = drmAlloc->getBO(); @@ -130,11 +129,15 @@ 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 != 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/os_interface/linux/drm_command_stream_tests.cpp b/unit_tests/os_interface/linux/drm_command_stream_tests.cpp index 1224e3ffff..47da4b7e2e 100644 --- a/unit_tests/os_interface/linux/drm_command_stream_tests.cpp +++ b/unit_tests/os_interface/linux/drm_command_stream_tests.cpp @@ -1364,6 +1364,29 @@ TEST_F(DrmCommandStreamLeaksTest, GivenAllocationsContainingDifferentCountOfFrag EXPECT_EQ(0u, hostPtrManager.getFragmentCount()); } +TEST_F(DrmCommandStreamLeaksTest, GivenTwoAllocationsWhenBackingStorageIsTheSameThenMakeResidentShouldAddOnlyOneLocation) { + auto ptr = (void *)0x1000; + auto size = MemoryConstants::pageSize; + auto ptr2 = (void *)0x1000; + + auto allocation = mm->allocateGraphicsMemory(size, ptr); + auto allocation2 = mm->allocateGraphicsMemory(size, ptr2); + + csr->makeResident(*allocation); + csr->makeResident(*allocation2); + + csr->processResidency(nullptr); + + EXPECT_EQ(tCsr->getResidencyVector()->size(), 1u); + + csr->makeNonResident(*allocation); + csr->makeNonResident(*allocation2); + + mm->freeGraphicsMemory(allocation); + mm->freeGraphicsMemory(allocation2); + mm->clearResidencyAllocations(); +} + TEST_F(DrmCommandStreamLeaksTest, makeResidentSizeZero) { std::unique_ptr buffer(this->createBO(0)); DrmAllocation allocation(buffer.get(), nullptr, buffer->peekSize());