summaryrefslogtreecommitdiffstats
path: root/src/Runtime/ogl-runtime/src/system/Qt3DSMemoryManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/ogl-runtime/src/system/Qt3DSMemoryManager.cpp')
-rw-r--r--src/Runtime/ogl-runtime/src/system/Qt3DSMemoryManager.cpp453
1 files changed, 453 insertions, 0 deletions
diff --git a/src/Runtime/ogl-runtime/src/system/Qt3DSMemoryManager.cpp b/src/Runtime/ogl-runtime/src/system/Qt3DSMemoryManager.cpp
new file mode 100644
index 00000000..a1ace59e
--- /dev/null
+++ b/src/Runtime/ogl-runtime/src/system/Qt3DSMemoryManager.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemory.h"
+#include "Qt3DSMemoryManager.h"
+#include "Qt3DSMemoryHeap.h"
+#include "Qt3DSMemoryProbe.h"
+#include "Qt3DSMemoryTracker.h"
+#include "Qt3DSMemoryStatistics.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Create a new empty memory pool manager.
+ *
+ * The manager must be initialized before use or it will forward all requests
+ * to the heap.
+ */
+CMemoryManager::CMemoryManager()
+{
+ // Set default allocations functions if they are not already set
+ if (NULL == CMemory::Malloc())
+ CMemory::SetMemoryFunctions(&malloc, &free, &realloc);
+
+ CMemoryStatistics::AddManager(this);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Q3DStudio_memset(m_Histogram, 0, sizeof(m_Histogram));
+ CMemoryStatistics::Overhead() += sizeof(m_Histogram);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Create a new initialized memory pool manager.
+ *
+ * @param inName short description of manager used in tracker
+ * @param inChunkSize array of values describing the chunk size of each pool
+ * @param inChunkCount array of values describing the number of chunks in each pool
+ */
+CMemoryManager::CMemoryManager(const CHAR *inName,
+ const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT])
+{
+ // Set default allocations functions if they are not already set
+ if (NULL == CMemory::Malloc())
+ CMemory::SetMemoryFunctions(&malloc, &free, &realloc);
+
+ CMemoryStatistics::AddManager(this);
+ Initialize(inName, inChunkSize, inChunkCount);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Q3DStudio_memset(m_Histogram, 0, sizeof(m_Histogram));
+ CMemoryStatistics::Overhead() -= sizeof(m_Histogram);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Release the memory manager and all owned pools.
+ *
+ * Nobody better point to memory in these pool because the it will be
+ * invalid after this.
+ */
+CMemoryManager::~CMemoryManager()
+{
+ CMemoryStatistics::RemoveManager(this);
+ Release();
+}
+
+//==============================================================================
+/**
+ * Configure the pool manager into separate pools of different chunk sizes.
+ *
+ * The chunk size array has to be increasing values such as:
+ * inChunkSize = { 8, 16, 32, 64, 96, 128, 256, 512, 1024 }
+ * but count doesn't:
+ * inChunkCount = { 500, 200, 1000, 200, 200, 100, 250, 50, 20 }
+ *
+ * The global memory manager settings are initialized in AKMemory.h
+ *
+ * @param inName short description of manager used in tracker
+ * @param inChunkSize array of Q3DStudio_MEMORY_POOLCOUNT values describing the chunk size
+ *of each pool
+ * @param inChunkCount array of Q3DStudio_MEMORY_POOLCOUNT values describing the number of
+ *chunks in each pool
+ */
+void CMemoryManager::Initialize(const CHAR *inName,
+ const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT])
+{
+ // Don't initialize more than once
+ Q3DStudio_ASSERT(m_Pool[0].GetChunkCount() == 0);
+ Q3DStudio_sprintf(m_Name, sizeof(m_Name), "%s", inName);
+
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ // Make sure pool are aligned to Q3DStudio_MEMORY_ALIGNMENT or smaller than
+ // Q3DStudio_MEMORY_ALIGNMENT
+ Q3DStudio_ASSERT(inChunkSize[thePoolIndex] < Q3DStudio_MEMORY_ALIGNMENT
+ || (inChunkSize[thePoolIndex] % Q3DStudio_MEMORY_ALIGNMENT) == 0);
+ m_Pool[thePoolIndex].Initialize(inName, inChunkSize[thePoolIndex],
+ inChunkCount[thePoolIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Release all the memory allocated in Initialize - essentially "uninitialize".
+ */
+void CMemoryManager::Release()
+{
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ m_Pool[thePoolIndex].Release();
+}
+
+//==============================================================================
+// ALLOCATION AND DEALLOCATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Fetch a new chunk of memory from the smallest pool possible
+ * @param inSize size of requested memory block, in bytes
+ * @param inType allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryManager::Allocate(INT32 inSize, const CHAR *inType, const CHAR *inFile,
+ const INT32 inLine)
+{
+ Q3DStudio_ASSERT(inSize >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Histogram[Q3DStudio_min<INT32>(inSize, 511)].Add(1);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ inSize += sizeof(CMemoryTracker::SMemoryInfo); // make room for SMemoryInfo
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ // Find the smallest pool that fits
+ void *thePointer = NULL;
+ INT32 thePoolIndex = 0;
+ while (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ // Does this pool fit?
+ if (inSize <= m_Pool[thePoolIndex].GetChunkSize()) {
+ thePointer = m_Pool[thePoolIndex].Allocate();
+ break;
+ }
+ ++thePoolIndex;
+ }
+
+ // // Record the amount of wasted bytes in this chunk
+ if (thePointer) {
+ // Basic tracking
+ m_ManagerData.m_Aligned.Allocate(inSize);
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_PoolData[thePoolIndex].m_Aligned.Allocate(inSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+ // If not, we go to the heap for now.
+ else {
+ // REFACTOR: Use the next pool size up instead?
+ thePointer = CMemoryHeap::Allocate(inSize, inType, inFile, inLine);
+ m_ManagerData.m_Overflow.Allocate(inSize);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ if (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT)
+ m_PoolData[thePoolIndex].m_Overflow.Allocate(
+ inSize); // Heap allocation due to full memory pool
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ CMemoryTracker::SMemoryInfo *theMemoryInfo =
+ reinterpret_cast<CMemoryTracker::SMemoryInfo *>(thePointer);
+
+ theMemoryInfo->m_DogTag = CMemoryTracker::TRACKER_DOGTAG;
+ theMemoryInfo->m_Line = static_cast<INT16>(inLine);
+ theMemoryInfo->m_Size = static_cast<INT16>(inSize - sizeof(CMemoryTracker::SMemoryInfo));
+ theMemoryInfo->m_File = inFile;
+ theMemoryInfo->m_Type = inType;
+
+ m_LineTracker.Remember(theMemoryInfo);
+ thePointer = reinterpret_cast<CMemoryTracker::SMemoryInfo *>(thePointer) + 1;
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ return thePointer;
+}
+
+//==============================================================================
+/**
+ * Release a chunk of memory.
+ * @param inPointer pointer to memory to be reused
+ * @param inSize size of the memory we are releasing, in bytes
+ */
+void CMemoryManager::Free(void *inPointer, INT32 inSize)
+{
+ if (!inPointer)
+ return;
+
+ Q3DStudio_ASSERT(inSize >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Histogram[Q3DStudio_min<INT32>(inSize, 511)].Delete(1);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ inPointer = reinterpret_cast<CMemoryTracker::SMemoryInfo *>(inPointer) - 1;
+ m_LineTracker.Forget(reinterpret_cast<CMemoryTracker::SMemoryInfo *>(inPointer));
+ inSize += sizeof(CMemoryTracker::SMemoryInfo);
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ // Did we get a valid pool?
+ INT32 thePoolIndex = FetchPoolIndex(inPointer);
+ if (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ m_Pool[thePoolIndex].Free(inPointer);
+ m_ManagerData.m_Aligned.Free(inSize);
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_PoolData[thePoolIndex].m_Aligned.Free(inSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ } else {
+ CMemoryHeap::Free(inPointer, inSize);
+ m_ManagerData.m_Overflow.Free(inSize);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ if (inSize <= m_Pool[Q3DStudio_MEMORY_POOLCOUNT - 1].GetChunkSize())
+ for (thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ if (inSize <= m_Pool[thePoolIndex].GetChunkSize()) {
+ m_PoolData[thePoolIndex].m_Overflow.Free(inSize);
+ // This is driving me crazy -CN.
+ // Q3DStudio_ASSERT( m_PoolData[thePoolIndex].m_Overflow.GetCalls(
+ // MEMSCOPE_GLOBAL, MEMVALUE_CURRENT ) >= 0 );
+ break;
+ }
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+}
+
+//==============================================================================
+/**
+ * Grow the existing memory allocated
+ *
+ * @param inOldPointer pointer given in a previous allocation
+ * @param inOldSize size of current memory block, in bytes
+ * @param inNewSize size of requested memory block, in bytes
+ * @param inNewType allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryManager::Reallocate(void *inOldPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewType, const CHAR *inFile, const INT32 inLine)
+{
+ Q3DStudio_ASSERT(inOldSize >= 0 && inNewSize >= 0);
+
+ // It's legal to pass NULL as old pointer to realloc
+ if (!inOldPointer)
+ return Allocate(inNewSize, inNewType, inFile, inLine);
+
+ if (inNewSize == 0) {
+ Free(inOldPointer, inOldSize);
+ return NULL;
+ }
+
+ // Get a new bigger chunk and transfer old data to it
+ void *thePointer = Allocate(inNewSize, inNewType, inFile, inLine);
+ Q3DStudio_memcpy(thePointer, inOldPointer, Q3DStudio_min(inOldSize, inNewSize));
+
+ // Release old data
+ Free(inOldPointer, inOldSize);
+ return thePointer;
+}
+
+//==============================================================================
+// IMPLEMENTATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Find the pool that owns the given pointer.
+ * @param inPointer pointer to memory to be found
+ * @return INT32 index of pool or Q3DStudio_MEMORY_POOLCOUNT if the chunk can't be found
+ */
+INT32 CMemoryManager::FetchPoolIndex(const void *inPointer)
+{
+ // Find pool that owns the pointer
+ INT32 thePoolIndex = 0;
+ while (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ if (m_Pool[thePoolIndex].OwnsChunk(inPointer))
+ return thePoolIndex;
+ ++thePoolIndex;
+ }
+
+ return Q3DStudio_MEMORY_POOLCOUNT;
+}
+
+//==============================================================================
+// STATISTICS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Return the text identifier of the manager
+ * @return the name, max 32 bytes long
+ */
+const CHAR *CMemoryManager::GetName()
+{
+ return m_Name;
+}
+
+//==============================================================================
+/**
+ * Reset all probe statistics
+ */
+void CMemoryManager::Reset()
+{
+ m_ManagerData.m_Aligned.Reset();
+ m_ManagerData.m_Overflow.Reset();
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ m_Pool[thePoolIndex].GetProbe().Reset();
+ m_PoolData[thePoolIndex].m_Aligned.Reset();
+ m_PoolData[thePoolIndex].m_Overflow.Reset();
+ }
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieve a particular memory pool
+ * @param inPoolIndex index of the pool
+ * @return SPoolData& is a reference to the indicated pool data
+ */
+CMemoryPool &CMemoryManager::GetPool(const INT32 inPoolIndex)
+{
+ Q3DStudio_ASSERT(inPoolIndex < Q3DStudio_MEMORY_POOLCOUNT && inPoolIndex >= 0);
+ return m_Pool[inPoolIndex];
+}
+
+//==============================================================================
+/**
+ * Retrieve a particular memory pool
+ * @param inPoolIndex index of the pool
+ * @return SPoolData& is a reference to the indicated pool data
+ */
+CMemoryManager::SPoolData *CMemoryManager::GetPoolData(const INT32 inPoolIndex)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inPoolIndex);
+ Q3DStudio_ASSERT(inPoolIndex < Q3DStudio_MEMORY_POOLCOUNT && inPoolIndex >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ return m_PoolData + inPoolIndex;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieve the number of bytes that were allocated on the heap
+ * @return CMemoryProbe as the heap statistics
+ */
+CMemoryManager::SPoolData &CMemoryManager::GetManagerData()
+{
+ return m_ManagerData;
+}
+
+//==============================================================================
+/**
+ * Sum the high level statistics of all the pools.
+ * @return CMemoryProbe as the statistics, calculated on the spot
+ */
+CMemoryProbe CMemoryManager::GetProbe()
+{
+ CMemoryProbe theProbe;
+#if Q3DStudio_MEMORY_POOLTRACKING
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ theProbe.Combine(m_Pool[thePoolIndex].GetProbe());
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ return theProbe;
+}
+
+//==============================================================================
+/**
+ * Fetch the tracker if enabled by setting Q3DStudio_MEMORY_LINETRACKING
+ * @return CMemoryTracker pointer or NULL
+ */
+CMemoryTracker *CMemoryManager::GetLineTracker()
+{
+#if Q3DStudio_MEMORY_LINETRACKING
+ return &m_LineTracker;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_LINETRACKING
+}
+
+//==============================================================================
+/**
+ * Fetch the histogram if enabled by setting Q3DStudio_MEMORY_HISTOGRAM.
+ * The histogram counts all requested allocations of the specific size.
+ * @return UINT16 array of 512 values, or NULL
+ */
+const CMemoryProbe::SValue *CMemoryManager::GetHistogram()
+{
+#if Q3DStudio_MEMORY_POOLTRACKING
+ return m_Histogram;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+} // namespace Q3DStudio