diff --git a/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp index 64c9a431e6..df87fa860c 100644 --- a/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +++ b/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -871,14 +871,29 @@ angle::Result Buffer11::getConstantBufferRangeStorage(const gl::Context *context while (mConstantBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize) { + // mMaxConstantBufferLruCount is 32-bit and wraps after 2^32 + // increments. After wraparound the freshly-touched entry can have + // the smallest lruCount. Exclude the entry we are currently + // working on from the eviction candidate set; the ASSERT below is + // a no-op in release builds and is not a sufficient guard. + const BufferStorage *currentStorage = newStorage; auto iter = std::min_element( std::begin(mConstantBufferRangeStoragesCache), std::end(mConstantBufferRangeStoragesCache), - [](const BufferCache::value_type &a, const BufferCache::value_type &b) { + [currentStorage](const BufferCache::value_type &a, + const BufferCache::value_type &b) { + // Treat the current entry as having lruCount = +inf so it + // is never the minimum. + if (a.second.storage == currentStorage) return false; + if (b.second.storage == currentStorage) return true; return a.second.lruCount < b.second.lruCount; }); - ASSERT(iter->second.storage != newStorage); + if (iter->second.storage == newStorage) + { + // Only one entry in the cache and it is ours. Cannot evict. + break; + } ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize()); mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize(); @@ -938,14 +953,30 @@ angle::Result Buffer11::getStructuredBufferRangeSRV(const gl::Context *context, while (mStructuredBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize) { - auto iter = std::min_element(std::begin(mStructuredBufferRangeStoragesCache), - std::end(mStructuredBufferRangeStoragesCache), - [](const StructuredBufferCache::value_type &a, - const StructuredBufferCache::value_type &b) { - return a.second.lruCount < b.second.lruCount; - }); - - ASSERT(iter->second.storage != newStorage); + // mMaxStructuredBufferLruCount is 32-bit and wraps after 2^32 + // increments. After wraparound the freshly-touched entry can have + // the smallest lruCount. Exclude the entry we are currently + // working on from the eviction candidate set; the ASSERT below is + // a no-op in release builds and is not a sufficient guard. + const BufferStorage *currentStorage = newStorage; + auto iter = + std::min_element(std::begin(mStructuredBufferRangeStoragesCache), + std::end(mStructuredBufferRangeStoragesCache), + [currentStorage](const StructuredBufferCache::value_type &a, + const StructuredBufferCache::value_type &b) { + // Treat the current entry as having + // lruCount = +inf so it is never the + // minimum. + if (a.second.storage == currentStorage) return false; + if (b.second.storage == currentStorage) return true; + return a.second.lruCount < b.second.lruCount; + }); + + if (iter->second.storage == newStorage) + { + // Only one entry in the cache and it is ours. Cannot evict. + break; + } ASSERT(mStructuredBufferStorageAdditionalSize >= iter->second.storage->getSize()); mStructuredBufferStorageAdditionalSize -= iter->second.storage->getSize();