BVB Source Codes

CRYENGINE Show ControllerDefragHeap.cpp Source code

Return Download CRYENGINE: download ControllerDefragHeap.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "stdafx.h"
  4. #include "ControllerDefragHeap.h"
  5.  
  6. #include "ControllerPQ.h"
  7.  
  8. CControllerDefragHeap::CControllerDefragHeap()
  9.         : m_pAddressRange(NULL)
  10.         , m_pAllocator(NULL)
  11.         , m_pBaseAddress(NULL)
  12.         , m_nPageSize(0)
  13.         , m_nLogPageSize(0)
  14.         , m_nBytesInFixedAllocs(0)
  15.         , m_numAvailableCopiesInFlight(MaxInFlightCopies)
  16.         , m_bytesInFlight(0)
  17.         , m_tickId(0)
  18.         , m_nLastCopyIdx(0)
  19.         , m_numQueuedCancels(0)
  20. {
  21. }
  22.  
  23. CControllerDefragHeap::~CControllerDefragHeap()
  24. {
  25.         if (m_pAllocator)
  26.         {
  27.                 // Release with discard because controller heap is global, and torn down with engine. This may
  28.                 // occur even though the character manager hasn't been destroyed, so allocations may still be active.
  29.                 // The engine is lost though, so it doesn't matter...
  30.                 m_pAllocator->Release(true);
  31.                 m_pAllocator = NULL;
  32.         }
  33. }
  34.  
  35. void CControllerDefragHeap::Init(size_t capacity)
  36. {
  37.         assert(!m_pAllocator);
  38.  
  39.         m_pAddressRange = CryGetIMemoryManager()->ReserveAddressRange(capacity, "Anim Defrag Heap");
  40.         m_pBaseAddress = m_pAddressRange->GetBaseAddress();
  41.         m_nPageSize = m_pAddressRange->GetPageSize();
  42.         m_nLogPageSize = IntegerLog2(m_nPageSize);
  43.  
  44.         capacity = Align(capacity, m_nPageSize);
  45.  
  46.         m_pAllocator = CryGetIMemoryManager()->CreateDefragAllocator();
  47.  
  48.         IDefragAllocator::Policy pol;
  49.         pol.pDefragPolicy = this;
  50.         pol.maxAllocs = MaxAllocs;
  51.         m_pAllocator->Init(capacity, MinAlignment, pol);
  52.  
  53.         m_numAllocsPerPage.resize(capacity >> m_nLogPageSize);
  54. }
  55.  
  56. CControllerDefragHeap::Stats CControllerDefragHeap::GetStats()
  57. {
  58.         Stats stats;
  59.  
  60.         stats.defragStats = m_pAllocator->GetStats();
  61.         stats.bytesInFixedAllocs = (size_t)m_nBytesInFixedAllocs;
  62.  
  63.         return stats;
  64. }
  65.  
  66. void CControllerDefragHeap::Update()
  67. {
  68.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ANIMATION);
  69.  
  70.         UpdateInflight(m_tickId);
  71.  
  72.         if (m_pAllocator != nullptr)
  73.         {
  74.                 m_pAllocator->DefragmentTick(
  75.                         (size_t)min((int)MaxScheduledCopiesPerUpdate, (int)m_numAvailableCopiesInFlight),
  76.                         (size_t)min((int)max(0, (int)MinFixedAllocSize - (int)m_bytesInFlight), (int)MaxScheduledBytesPerUpdate));
  77.         }
  78.  
  79.         ++m_tickId;
  80. }
  81.  
  82. CControllerDefragHdl CControllerDefragHeap::AllocPinned(size_t sz, IControllerRelocatableChain* pContext)
  83. {
  84.         CControllerDefragHdl ret;
  85.  
  86.         if (sz < MinFixedAllocSize)
  87.         {
  88.                 IDefragAllocator::AllocatePinnedResult apr = m_pAllocator->AllocatePinned(sz, "", pContext);
  89.  
  90.                 if (apr.hdl != IDefragAllocator::InvalidHdl)
  91.                 {
  92.                         // Ensure that the requisite pages are mapped
  93.                         if (IncreaseRange(apr.offs, apr.usableSize))
  94.                         {
  95.                                 ret = CControllerDefragHdl(apr.hdl);
  96.  
  97.                                 MEMREPLAY_SCOPE(EMemReplayAllocClass::C_UserPointer, EMemReplayUserPointerClass::C_CryMalloc);
  98.                                 MEMREPLAY_SCOPE_ALLOC(m_pBaseAddress + apr.offs, apr.usableSize, MinAlignment);
  99.                         }
  100.                         else
  101.                         {
  102.                                 m_pAllocator->Free(apr.hdl);
  103.                         }
  104.                 }
  105.                 else if (AllowGPHFallback)
  106.                 {
  107.                         MEMREPLAY_SCOPE(EMemReplayAllocClass::C_UserPointer, EMemReplayUserPointerClass::C_CryMalloc);
  108.  
  109.                         ret = CControllerDefragHdl(FixedAlloc(sz, true));
  110.  
  111.                         if (ret.IsValid())
  112.                         {
  113.                                 MEMREPLAY_SCOPE_ALLOC(ret.AsFixed(), UsableSize(ret), MinAlignment);
  114.                         }
  115.                 }
  116.         }
  117.         else
  118.         {
  119.                 MEMREPLAY_SCOPE(EMemReplayAllocClass::C_UserPointer, EMemReplayUserPointerClass::C_CryMalloc);
  120.  
  121.                 ret = CControllerDefragHdl(FixedAlloc(sz, false));
  122.  
  123.                 if (ret.IsValid())
  124.                 {
  125.                         MEMREPLAY_SCOPE_ALLOC(ret.AsFixed(), UsableSize(ret), MinAlignment);
  126.                 }
  127.         }
  128.  
  129.         return ret;
  130. }
  131.  
  132. void CControllerDefragHeap::Free(CControllerDefragHdl hdl)
  133. {
  134.         if (!hdl.IsFixed())
  135.         {
  136.                 UINT_PTR offs = m_pAllocator->Pin(hdl.AsHdl());
  137.  
  138.                 {
  139.                         MEMREPLAY_SCOPE(EMemReplayAllocClass::C_UserPointer, EMemReplayUserPointerClass::C_CryMalloc);
  140.                         MEMREPLAY_SCOPE_FREE(m_pBaseAddress + offs);
  141.                 }
  142.  
  143.                 assert(hdl.IsValid());
  144.  
  145.                 // Ensure that pages are unmapped
  146.                 UINT_PTR sz = m_pAllocator->UsableSize(hdl.AsHdl());
  147.  
  148.                 DecreaseRange(offs, sz);
  149.  
  150.                 m_pAllocator->Free(hdl.AsHdl());
  151.         }
  152.         else
  153.         {
  154.                 MEMREPLAY_SCOPE(EMemReplayAllocClass::C_UserPointer, EMemReplayUserPointerClass::C_CryMalloc);
  155.  
  156.                 FixedFree(hdl.AsFixed());
  157.  
  158.                 MEMREPLAY_SCOPE_FREE(hdl.AsFixed());
  159.         }
  160. }
  161.  
  162. size_t CControllerDefragHeap::UsableSize(CControllerDefragHdl hdl)
  163. {
  164.         assert(hdl.IsValid());
  165.         if (!hdl.IsFixed())
  166.         {
  167.                 return m_pAllocator->UsableSize(hdl.AsHdl());
  168.         }
  169.         else
  170.         {
  171.                 FixedHdr* pHdr = ((FixedHdr*)hdl.AsFixed()) - 1;
  172.                 return pHdr->size;
  173.         }
  174. }
  175.  
  176. uint32 CControllerDefragHeap::BeginCopy(void* pContext, UINT_PTR dstOffset, UINT_PTR srcOffset, UINT_PTR size, IDefragAllocatorCopyNotification* pNotification)
  177. {
  178.         // Try and boost the destination range
  179.         if (IncreaseRange(dstOffset, size))
  180.         {
  181.                 uint32 nLastId = m_nLastCopyIdx;
  182.                 uint32 nIdx = (uint32) - 1;
  183.  
  184.                 for (uint32 i = 0; i < MaxInFlightCopies; ++i)
  185.                 {
  186.                         if (!m_copiesInFlight[(nLastId + i) % MaxInFlightCopies].inUse)
  187.                         {
  188.                                 nIdx = (nLastId + i) % MaxInFlightCopies;
  189.                                 break;
  190.                         }
  191.                 }
  192.  
  193.                 if (nIdx != (uint32) - 1)
  194.                 {
  195.                         assert(nIdx >= 0 && nIdx < CRY_ARRAY_COUNT(m_copiesInFlight));
  196.                         Copy& cp = m_copiesInFlight[nIdx];
  197.                         stl::reconstruct(cp, pContext, dstOffset, srcOffset, size, pNotification);
  198.  
  199.                         if (cp.size >= MinJobCopySize)
  200.                         {
  201.                                 // Boost the src region so it will remain valid during the copy
  202.                                 IncreaseRange(srcOffset, size);
  203.  
  204.                                 cp.jobState = 1;
  205.                                 cryAsyncMemcpy(m_pBaseAddress + cp.dstOffset, m_pBaseAddress + cp.srcOffset, cp.size, MC_CPU_TO_CPU, &cp.jobState);
  206.                         }
  207.                         else
  208.                         {
  209.                                 memcpy(m_pBaseAddress + cp.dstOffset, m_pBaseAddress + cp.srcOffset, cp.size);
  210.                                 cp.pNotification->bDstIsValid = true;
  211.                         }
  212.  
  213.                         --m_numAvailableCopiesInFlight;
  214.                         m_bytesInFlight += cp.size;
  215.                         m_nLastCopyIdx = nIdx;
  216.  
  217.                         return nIdx + 1;
  218.                 }
  219.         }
  220.  
  221.         return 0;
  222. }
  223.  
  224. void CControllerDefragHeap::Relocate(uint32 userMoveId, void* pContext, UINT_PTR newOffset, UINT_PTR oldOffset, UINT_PTR size)
  225. {
  226.         Copy& cp = m_copiesInFlight[userMoveId - 1];
  227.         if (cp.inUse && (cp.pContext == pContext))
  228.         {
  229. #ifndef _RELEASE
  230.                 if (cp.relocated)
  231.                         __debugbreak();
  232. #endif
  233.  
  234.                 char* pNewBase = m_pBaseAddress + newOffset;
  235.                 char* pOldBase = m_pBaseAddress + oldOffset;
  236.  
  237.                 for (IControllerRelocatableChain* rbc = (IControllerRelocatableChain*)pContext; rbc; rbc = rbc->GetNext())
  238.                         rbc->Relocate(pNewBase, pOldBase);
  239.  
  240.                 MEMREPLAY_SCOPE(EMemReplayAllocClass::C_UserPointer, EMemReplayUserPointerClass::C_CryMalloc);
  241.                 MEMREPLAY_SCOPE_REALLOC(m_pBaseAddress + oldOffset, m_pBaseAddress + newOffset, size, MinAlignment);
  242.  
  243.                 cp.relocateFrameId = m_tickId;
  244.                 cp.relocated = true;
  245.                 return;
  246.         }
  247.  
  248. #ifndef _RELEASE
  249.         __debugbreak();
  250. #endif
  251. }
  252.  
  253. void CControllerDefragHeap::CancelCopy(uint32 userMoveId, void* pContext, bool bSync)
  254. {
  255.         CryAutoLock<CryCriticalSectionNonRecursive> lock(m_queuedCancelLock);
  256. #ifndef _RELEASE
  257.         if (m_numQueuedCancels == CRY_ARRAY_COUNT(m_queuedCancels))
  258.                 __debugbreak();
  259. #endif
  260.         assert(m_numQueuedCancels < CRY_ARRAY_COUNT(m_queuedCancels));
  261.         m_queuedCancels[m_numQueuedCancels++] = userMoveId;
  262. }
  263.  
  264. void CControllerDefragHeap::SyncCopy(void* pContext, UINT_PTR dstOffset, UINT_PTR srcOffset, UINT_PTR size)
  265. {
  266.         // Not supported - but shouldn't be needed.
  267.         __debugbreak();
  268. }
  269.  
  270. bool CControllerDefragHeap::IncreaseRange(UINT_PTR offs, UINT_PTR sz)
  271. {
  272.         UINT_PTR basePageIdx = offs >> m_nLogPageSize;
  273.         UINT_PTR lastPageIdx = (offs + sz + m_nPageSize - 1) >> m_nLogPageSize;
  274.  
  275.         CryAutoLock<CryCriticalSectionNonRecursive> lock(m_pagesLock);
  276.  
  277.         for (UINT_PTR pageIdx = basePageIdx; pageIdx != lastPageIdx; ++pageIdx)
  278.         {
  279.                 if ((++m_numAllocsPerPage[pageIdx]) == 1)
  280.                 {
  281.                         if (!m_pAddressRange->MapPage(pageIdx))
  282.                         {
  283.                                 // Failed to allocate. Unwind mapping.
  284.                                 DecreaseRange_Locked(offs, (pageIdx - basePageIdx) * m_nPageSize);
  285.                                 return false;
  286.                         }
  287.                 }
  288.         }
  289.  
  290.         return true;
  291. }
  292.  
  293. void CControllerDefragHeap::DecreaseRange(UINT_PTR offs, UINT_PTR sz)
  294. {
  295.         CryAutoLock<CryCriticalSectionNonRecursive> lock(m_pagesLock);
  296.         DecreaseRange_Locked(offs, sz);
  297. }
  298.  
  299. void CControllerDefragHeap::DecreaseRange_Locked(UINT_PTR offs, UINT_PTR sz)
  300. {
  301.         UINT_PTR basePageIdx = offs >> m_nLogPageSize;
  302.         UINT_PTR lastPageIdx = (offs + sz + m_nPageSize - 1) >> m_nLogPageSize;
  303.  
  304.         for (UINT_PTR pageIdx = basePageIdx; pageIdx != lastPageIdx; ++pageIdx)
  305.         {
  306.                 if (!(--m_numAllocsPerPage[pageIdx]))
  307.                         m_pAddressRange->UnmapPage(pageIdx);
  308.         }
  309. }
  310.  
  311. void* CControllerDefragHeap::FixedAlloc(size_t sz, bool bFromGPH)
  312. {
  313.         PREFAST_SUPPRESS_WARNING(6240) // did not intend to use bitwise-and, its just a bool check
  314.         if (bFromGPH && AllowGPHFallback)
  315.         {
  316.                 FixedHdr* p = (FixedHdr*)CryModuleMalloc(sz + sizeof(FixedHdr));
  317.                 if (p)
  318.                 {
  319.                         CryInterlockedAdd(&m_nBytesInFixedAllocs, (int)sz);
  320.  
  321.                         p->size = sz;
  322.                         p->bFromGPH = true;
  323.                         return p + 1;
  324.                 }
  325.         }
  326.  
  327.         FixedHdr* p = (FixedHdr*)CryGetIMemoryManager()->AllocPages(sz + sizeof(FixedHdr));
  328.         if (p)
  329.         {
  330.                 CryInterlockedAdd(&m_nBytesInFixedAllocs, (int)sz);
  331.  
  332.                 p->size = sz;
  333.                 p->bFromGPH = false;
  334.                 return p + 1;
  335.         }
  336.         else
  337.         {
  338.                 return NULL;
  339.         }
  340. }
  341.  
  342. void CControllerDefragHeap::FixedFree(void* p)
  343. {
  344.         FixedHdr* fh = ((FixedHdr*)p) - 1;
  345.         CryInterlockedAdd(&m_nBytesInFixedAllocs, -(int)fh->size);
  346.  
  347.         PREFAST_SUPPRESS_WARNING(6239) // did not intend to use bitwise-and, its just a bool check
  348.         if (AllowGPHFallback && fh->bFromGPH)
  349.                 CryModuleFree(fh);
  350.         else
  351.                 CryGetIMemoryManager()->FreePages(fh, (size_t)fh->size);
  352. }
  353.  
  354. void CControllerDefragHeap::UpdateInflight(int frameId)
  355. {
  356.         if (m_numAvailableCopiesInFlight != MaxInFlightCopies)
  357.         {
  358.                 uint32 pQueuedCancels[MaxInFlightCopies];
  359.                 int nQueuedCancels = 0;
  360.  
  361.                 {
  362.                         CryAutoLock<CryCriticalSectionNonRecursive> lock(m_queuedCancelLock);
  363.                         memcpy(pQueuedCancels, m_queuedCancels, m_numQueuedCancels * sizeof(pQueuedCancels[0]));
  364.                         nQueuedCancels = m_numQueuedCancels;
  365.                         m_numQueuedCancels = 0;
  366.                 }
  367.  
  368.                 std::sort(pQueuedCancels, pQueuedCancels + nQueuedCancels);
  369.                 nQueuedCancels = (int)std::distance(pQueuedCancels, std::unique(pQueuedCancels, pQueuedCancels + nQueuedCancels));
  370.  
  371.                 for (int32 i = 0; i < MaxInFlightCopies; ++i)
  372.                 {
  373.                         Copy& cp = m_copiesInFlight[i];
  374.  
  375.                         if (cp.inUse)
  376.                         {
  377.                                 if (std::binary_search(pQueuedCancels, pQueuedCancels + nQueuedCancels, (uint32)(i + 1)))
  378.                                         cp.cancelled = true;
  379.  
  380.                                 bool bDone = false;
  381.  
  382.                                 if (cp.jobState >= 0)
  383.                                 {
  384.                                         if (cp.jobState == 0)
  385.                                         {
  386.                                                 // Undo the boost for the copy
  387.                                                 DecreaseRange(cp.srcOffset, cp.size);
  388.                                                 cp.pNotification->bDstIsValid = true;
  389.                                                 cp.jobState = -1;
  390.                                         }
  391.                                 }
  392.                                 else if (cp.relocateFrameId)
  393.                                 {
  394.                                         if ((frameId - cp.relocateFrameId) >= CompletionLatencyFrames)
  395.                                         {
  396.                                                 cp.pNotification->bSrcIsUnneeded = true;
  397.                                                 cp.relocateFrameId = 0;
  398.                                                 bDone = true;
  399.                                         }
  400.                                 }
  401.                                 else if (cp.cancelled)
  402.                                 {
  403.                                         cp.pNotification->bSrcIsUnneeded = true;
  404.                                         bDone = true;
  405.                                 }
  406.  
  407.                                 if (bDone)
  408.                                 {
  409.                                         if (cp.cancelled && !cp.relocated)
  410.                                                 DecreaseRange(cp.dstOffset, cp.size);
  411.                                         else
  412.                                                 DecreaseRange(cp.srcOffset, cp.size);
  413.  
  414.                                         cp.inUse = false;
  415.                                         ++m_numAvailableCopiesInFlight;
  416.                                         m_bytesInFlight -= cp.size;
  417.                                 }
  418.                         }
  419.                 }
  420.         }
  421. }
  422.  
downloadControllerDefragHeap.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top