Created
April 27, 2019 21:55
-
-
Save devshgraphicsprogramming/d966f2454dd77660a05896d1fd5691ed to your computer and use it in GitHub Desktop.
Garbage Collection, fencing, etc. Without Separate Memory Arenas [EARLY PROTOTYPE]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <class T> | |
class STLCompatibleGPUAllocator : public irr::core::AllocatorTrivialBase<T> | |
{ | |
public: | |
typedef size_t size_type; | |
typedef T* pointer; | |
template< class U> struct rebind { typedef STLCompatibleGPUAllocator<U> other; }; | |
STLCompatibleGPUAllocator() {} | |
virtual ~STLCompatibleGPUAllocator() {} | |
template<typename U> | |
STLCompatibleGPUAllocator(const STLCompatibleGPUAllocator<U>& other) {} | |
template<typename U> | |
STLCompatibleGPUAllocator(STLCompatibleGPUAllocator<U>&& other) {} | |
T* allocate(size_type n, const void* hint=nullptr) noexcept; | |
void deallocate(T* p, size_type n) noexcept; | |
template<typename U> | |
inline bool operator!=(const STLCompatibleGPUAllocator<U>& other) const noexcept | |
{ | |
return false; | |
} | |
template<typename U> | |
inline bool operator==(const STLCompatibleGPUAllocator<U>& other) const noexcept | |
{ | |
return true; | |
} | |
// a little extra for copying contents between this allocator's memory and other buffer | |
inline void copyToBuffer(video::IGPUBuffer* outBuff, size_t offset, void* dataPtr, size_t dataSize) noexcept; | |
}; | |
template<typename T> | |
inline T* STLCompatibleGPUAllocator<T>::allocate(size_type n, const void* hint) noexcept | |
{ | |
auto actualAllocatorPointer = GLOBAL_READ_WRITE_STREAMING_BUFFER; // of type video::StreamingTransientDataBufferMT<> | |
uint32_t addr = video::StreamingTransientDataBufferMT<>::invalid_address; | |
const uint32_t bytes = n*sizeof(T); | |
const uint32_t alignment = 64u; // for teh lulz | |
const bool isMainThread = true; // for now, TODO | |
while (actualAllocatorPointer->multi_alloc(std::chrono::microseconds(1u),1u,&addr,&bytes,&alignment)) | |
{ | |
std::this_thread::yield(); | |
} | |
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(actualAllocatorPointer->getBufferPointer())+addr); | |
} | |
template<typename T> | |
inline void STLCompatibleGPUAllocator<T>::deallocate(T* p, size_type n) noexcept | |
{ | |
auto actualAllocatorPointer = GLOBAL_READ_WRITE_STREAMING_BUFFER; // of type video::StreamingTransientDataBufferMT<> | |
uint32_t addr = reinterpret_cast<uint8_t*>(p)-reinterpret_cast<uint8_t*>(actualAllocatorPointer->getBufferPointer()); | |
const uint32_t bytes = n*sizeof(T); | |
actualAllocatorPointer->multi_free(1u,&addr,&bytes); // no fence placed unfortunately | |
} | |
template<typename T> | |
inline void STLCompatibleGPUAllocator<T>::copyToBuffer(video::IGPUBuffer* outBuff, size_t offset, void* dataPtr, size_t dataSize) noexcept | |
{ | |
auto actualAllocatorPointer = GLOBAL_READ_WRITE_STREAMING_BUFFER; // of type video::StreamingTransientDataBufferMT<> | |
uint32_t addr = reinterpret_cast<uint8_t*>(dataPtr)-reinterpret_cast<uint8_t*>(actualAllocatorPointer->getBufferPointer()); | |
#ifdef _IRR_DEBUG | |
assert(addr<actualAllocatorPointer->getBuffer()->getSize()); | |
#endif // _IRR_DEBUG | |
if (actualAllocatorPointer->needsManualFlushOrInvalidate()) | |
gDriver->flushMappedMemoryRanges({{actualAllocatorPointer->getBuffer()->getBoundMemory(),addr,dataSize}}); | |
gDriver->copyBuffer(actualAllocatorPointer->getBuffer(),outBuff,addr,offset,dataSize); | |
} | |
template<typename T> | |
class VectorFreeFunctor | |
{ | |
public: | |
typedef core::vector<T,STLCompatibleGPUAllocator<uint32_t>*> VectorType; | |
VectorFreeFunctor(VectorType&& inVec) : vecToDelete(std::forward<VectorType>(inVec)) | |
{ | |
} | |
VectorFreeFunctor(const VectorFreeFunctor& other) = delete; | |
VectorFreeFunctor(VectorFreeFunctor&& other) | |
{ | |
this->operator=(std::forward<VectorFreeFunctor>(other)); | |
} | |
VectorFreeFunctor& operator=(const VectorFreeFunctor& other) = delete; | |
inline VectorFreeFunctor& operator=(VectorFreeFunctor&& other) | |
{ | |
std::swap(vecToDelete,other.vecToDelete); | |
return *this; | |
} | |
inline bool operator()(uint32_t& unallocatedSize) | |
{ | |
if (unallocatedSize==0u) | |
return; | |
if (!vecToDelete) | |
continue; | |
size_t capacity = vecToDelete->capacity()*sizeof(VectorType); | |
if (unallocatedSize<=capacity) | |
{ | |
unallocatedSize = 0u; | |
break; | |
} | |
unallocatedSize -= capacity; | |
operator()(); | |
return unallocatedSize==0u; | |
} | |
inline void operator()() | |
{ | |
delete vecToDelete; | |
} | |
private: | |
VectorType* vecToDelete; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment