/* * Copyright (C) 2023-2025 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "shared/source/helpers/constants.h" #include "shared/source/helpers/non_copyable_or_moveable.h" #include "shared/source/utilities/stackvec.h" #include #include #include #include #include namespace NEO { class GraphicsAllocation; class HeapAllocator; class MemoryManager; class ProductHelper; struct SmallBuffersParams { size_t aggregatedSmallBuffersPoolSize{0}; size_t smallBufferThreshold{0}; size_t chunkAlignment{0}; size_t startingOffset{0}; static SmallBuffersParams getDefaultParams() { return { .aggregatedSmallBuffersPoolSize = 2 * MemoryConstants::megaByte, .smallBufferThreshold = 1 * MemoryConstants::megaByte, .chunkAlignment = MemoryConstants::pageSize64k, .startingOffset = MemoryConstants::pageSize64k}; } static SmallBuffersParams getLargePagesParams() { return { .aggregatedSmallBuffersPoolSize = 16 * MemoryConstants::megaByte, .smallBufferThreshold = 2 * MemoryConstants::megaByte, .chunkAlignment = MemoryConstants::pageSize64k, .startingOffset = MemoryConstants::pageSize64k}; } static inline SmallBuffersParams getPreferredBufferPoolParams(const ProductHelper &productHelper); }; template struct AbstractBuffersPool : public NonCopyableClass { // The prototype of a function allocating the `mainStorage` is not specified. // That would be an unnecessary limitation here - it is completely up to derived class implementation. // Perhaps the allocating function needs to leverage `HeapAllocator::allocate()` and also // a BufferType-dependent function reserving chunks within `mainStorage`. // Example: see `NEO::Context::BufferPool::allocate()` using AllocsVecCRef = const StackVec &; using OnChunkFreeCallback = void (PoolT::*)(uint64_t offset, size_t size); AbstractBuffersPool(MemoryManager *memoryManager, OnChunkFreeCallback onChunkFreeCallback); AbstractBuffersPool(MemoryManager *memoryManager, OnChunkFreeCallback onChunkFreeCallback, const SmallBuffersParams ¶ms); AbstractBuffersPool(AbstractBuffersPool &&bufferPool); AbstractBuffersPool &operator=(AbstractBuffersPool &&other) noexcept = delete; virtual ~AbstractBuffersPool() = default; void tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size); bool isPoolBuffer(const BufferParentType *buffer) const; void drain(); // Derived class needs to provide its own implementation of getAllocationsVector(). // This is a CRTP-replacement for virtual functions. AllocsVecCRef getAllocationsVector() { return static_cast(this)->getAllocationsVector(); } MemoryManager *memoryManager{nullptr}; std::unique_ptr mainStorage; std::unique_ptr chunkAllocator; std::vector> chunksToFree; OnChunkFreeCallback onChunkFreeCallback = nullptr; SmallBuffersParams params; }; template class AbstractBuffersAllocator { // The prototype of a function allocating buffers from the pool is not specified (see similar comment in `AbstractBufersPool`). // By common sense, in order to allocate buffers from the pool the function should leverage a call provided by `BuffersPoolType`. // Example: see `NEO::Context::BufferPoolAllocator::allocateBufferFromPool()`. public: AbstractBuffersAllocator(const SmallBuffersParams ¶ms); AbstractBuffersAllocator(); void releasePools() { this->bufferPools.clear(); } bool isPoolBuffer(const BufferParentType *buffer) const; void tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size); uint32_t getPoolsCount() { return static_cast(this->bufferPools.size()); } void setParams(const SmallBuffersParams &newParams) { params = newParams; } SmallBuffersParams getParams() const { return params; }; protected: inline bool isSizeWithinThreshold(size_t size) const { return params.smallBufferThreshold >= size; } void tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size, std::vector &bufferPoolsVec); void drain(); void drain(std::vector &bufferPoolsVec); void addNewBufferPool(BuffersPoolType &&bufferPool); void addNewBufferPool(BuffersPoolType &&bufferPool, std::vector &bufferPoolsVec); std::mutex mutex; std::vector bufferPools; SmallBuffersParams params; }; } // namespace NEO