1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: MemoryManager.cpp 4 5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Rev: 47228 $ 14 *---------------------------------------------------------------------------*/ 15 16 #include "MemoryManager.h" 17 18 #define DEBUG_PRINT 0 19 20 namespace demo 21 { 22 23 namespace memory_manager 24 { 25 namespace 26 { 27 const int ALIGNMENT_SYSTEM_BUFFER = 4; // Specify the maximum among the rules 28 const int ALIGNMENT_VERTEX = 4; // Take into account 4-byte alignment rules for GLfloat type 29 const int ALIGNMENT_TEXTURE = 128; 30 const int ALIGNMENT_RENDER_BUFFER = 64; // 24-bit format depth buffer (D24) must be aligned to 96 bytes 31 const int ALIGNMENT_DISPLAY_BUFFER = 16; 32 const int ALIGNMENT_3D_COMMAND_BUFFER = 16; 33 MathRoundup(uptr x,int base)34 inline uptr MathRoundup(uptr x, int base) 35 { 36 return ((x) + ((base)-1)) & ~((base)-1); 37 } 38 } 39 40 namespace detail 41 { MemoryManager()42 MemoryManager::MemoryManager() : 43 m_Initialized(false), 44 m_pStartAddrFcram(NULL), 45 m_CurrentAddrVramA(NULL), 46 m_CurrentAddrVramB(NULL), 47 m_HeapOnFcram(), 48 m_AllocatedBlockSize(0), 49 m_DebugPrint(false) 50 { 51 } 52 ~MemoryManager()53 MemoryManager::~MemoryManager() 54 { 55 Finalize(); 56 } 57 Initialize(const uptr fcramAddress,const size_t memorySize)58 void MemoryManager::Initialize(const uptr fcramAddress, const size_t memorySize) 59 { 60 if (m_Initialized) 61 { 62 return; 63 } 64 65 m_pStartAddrFcram = fcramAddress; 66 NN_TASSERT_(m_pStartAddrFcram != NULL); 67 68 m_AllocatedBlockSize = memorySize; 69 70 m_HeapOnFcram.Initialize(m_pStartAddrFcram, memorySize ); 71 72 m_CurrentAddrVramA = nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMA); 73 m_CurrentAddrVramB = nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMB); 74 75 #if DEBUG_PRINT 76 NN_TLOG_("[demo::MemoryManager] Start address in Main Memory (FCRAM): 0x%08X\n", m_pStartAddrFcram); 77 NN_TLOG_("[demo::MemoryManager] Start address in VRAM-A: 0x%08X\n", m_CurrentAddrVramA); 78 NN_TLOG_("[demo::MemoryManager] Start address in VRAM-B: 0x%08X\n", m_CurrentAddrVramB); 79 #endif 80 81 m_Initialized = true; 82 } 83 Finalize(void)84 void MemoryManager::Finalize(void) 85 { 86 m_HeapOnFcram.Finalize(); 87 88 m_Initialized = false; 89 } 90 PrintFreeMemorySize(void)91 void MemoryManager::PrintFreeMemorySize(void) 92 { 93 NN_TLOG_("[demo::MemoryManager] Free memory size in Main Memory (FCRAM) is 0x%06X(max 0x%06X)\n", 94 m_HeapOnFcram.GetTotalFreeSize(), m_AllocatedBlockSize); 95 NN_TLOG_("[demo::MemoryManager] Free memory size in VRAM-A is 0x%06X(max 0x%06X)\n", 96 nn::gx::GetVramEndAddr(nn::gx::MEM_VRAMA) - m_CurrentAddrVramA, nn::gx::GetVramSize(nn::gx::MEM_VRAMA)); 97 NN_TLOG_("[demo::MemoryManager] Free memory size in VRAM-B is 0x%06X(max 0x%06X)\n", 98 nn::gx::GetVramEndAddr(nn::gx::MEM_VRAMB) - m_CurrentAddrVramB, nn::gx::GetVramSize(nn::gx::MEM_VRAMB)); 99 } 100 Allocate(GLenum area,GLenum aim,GLuint id,GLsizei size)101 void* MemoryManager::Allocate(GLenum area, GLenum aim, GLuint id, GLsizei size) 102 { 103 if (!m_Initialized) 104 { 105 NN_TPANIC_("Not initialized.\n"); 106 } 107 108 if (size == 0) 109 return 0; 110 111 // When allocating to VRAM, the VRAM can be treated as a stack due to its simplicity 112 // In addition, do not respond to fragmentation 113 // In order to handle fragmentation, information to be stored in allocated memory named area, aim, and id when allocation succeeds must be saved before subsequent deallocation. 114 // 115 116 int addrAlign = 8; 117 void* resultAddr = NULL; 118 119 // Take into account the alignment restrictions on each data set's position 120 switch (aim) 121 { 122 case NN_GX_MEM_SYSTEM: 123 addrAlign = ALIGNMENT_SYSTEM_BUFFER; 124 break; 125 case NN_GX_MEM_TEXTURE: 126 addrAlign = ALIGNMENT_TEXTURE; 127 break; 128 case NN_GX_MEM_VERTEXBUFFER: 129 addrAlign = ALIGNMENT_VERTEX; 130 break; 131 case NN_GX_MEM_RENDERBUFFER: 132 addrAlign = ALIGNMENT_RENDER_BUFFER; 133 break; 134 case NN_GX_MEM_DISPLAYBUFFER: 135 addrAlign = ALIGNMENT_DISPLAY_BUFFER; 136 break; 137 case NN_GX_MEM_COMMANDBUFFER: 138 addrAlign = ALIGNMENT_3D_COMMAND_BUFFER; 139 break; 140 default: 141 NN_TPANIC_("Invalid parameter. (0x%X)\n", aim); 142 break; 143 } 144 145 switch (area) 146 { 147 case NN_GX_MEM_FCRAM: 148 // When using FCRAM, no need to manage this because it is allocated from the expanded heap that is supported by the SDK 149 if ( (resultAddr = m_HeapOnFcram.Allocate(size, addrAlign)) == NULL) 150 { 151 NN_TPANIC_("Lack of resources in Main Memory (FCRAM).\n"); 152 } 153 break; 154 case NN_GX_MEM_VRAMA: 155 { 156 if (MathRoundup(m_CurrentAddrVramA, addrAlign) + size > nn::gx::GetVramEndAddr(nn::gx::MEM_VRAMA)) 157 { 158 NN_TPANIC_("Lack of resources in VRAM-A.\n"); 159 } 160 161 m_CurrentAddrVramA = MathRoundup(m_CurrentAddrVramA, addrAlign); 162 resultAddr = reinterpret_cast<void*>(m_CurrentAddrVramA); 163 m_CurrentAddrVramA += size; 164 } 165 break; 166 case NN_GX_MEM_VRAMB: 167 { 168 if (MathRoundup(m_CurrentAddrVramB, addrAlign) + size > nn::gx::GetVramEndAddr(nn::gx::MEM_VRAMB)) 169 { 170 NN_TPANIC_("Lack of resources in VRAM-B.\n"); 171 } 172 173 m_CurrentAddrVramB = MathRoundup(m_CurrentAddrVramB, addrAlign); 174 resultAddr = reinterpret_cast<void*>(m_CurrentAddrVramB); 175 m_CurrentAddrVramB += size; 176 } 177 break; 178 default: 179 // This is not likely in normal use; PANIC 180 NN_TPANIC_("Invalid parameter. (0x%X)\n", area); 181 break; 182 } 183 184 #if DEBUG_PRINT 185 if (aim == NN_GX_MEM_SYSTEM) 186 { 187 NN_TLOG_("[demo::MemoryManager] NN_GX_MEM_SYSTEM is allocated at 0x%08X - 0x%08X on %X\n", 188 resultAddr, 189 reinterpret_cast<int>(resultAddr) + size - 1, area); 190 } 191 else if (aim == NN_GX_MEM_TEXTURE) 192 { 193 NN_TLOG_("[demo::MemoryManager] NN_GX_MEM_TEXTURE(id:%d) is allocated at 0x%08X - 0x%08X on %X\n", 194 resultAddr, id 195 reinterpret_cast<int>(resultAddr) + size - 1, area); 196 } 197 else if (aim == NN_GX_MEM_VERTEXBUFFER) 198 { 199 NN_TLOG_("[demo::MemoryManager] NN_GX_MEM_VERTEXBUFFER(id:%d) is allocated at 0x%08X - 0x%08X on %X\n", 200 resultAddr, id 201 reinterpret_cast<int>(resultAddr) + size - 1, area); 202 } 203 else if (aim == NN_GX_MEM_DISPLAYBUFFER) 204 { 205 NN_TLOG_("[demo::MemoryManager] NN_GX_MEM_DISPLAYBUFFER(id:%d) is allocated at 0x%08X - 0x%08X on %X\n", 206 resultAddr, id 207 reinterpret_cast<int>(resultAddr) + size - 1, area); 208 } 209 else if (aim == NN_GX_MEM_RENDERBUFFER) 210 { 211 NN_TLOG_("[demo::MemoryManager] NN_GX_MEM_RENDERBUFFER(id:%d) is allocated at 0x%08X - 0x%08X on %X\n", 212 resultAddr, id 213 reinterpret_cast<int>(resultAddr) + size - 1, area); 214 } 215 else if (aim == NN_GX_MEM_COMMANDBUFFER) 216 { 217 NN_TLOG_("[demo::MemoryManager] NN_GX_MEM_COMMANDBUFFER(id:%d) is allocated at 0x%08X - 0x%08X on %X\n", 218 resultAddr, id 219 reinterpret_cast<int>(resultAddr) + size - 1, area); 220 } 221 #else 222 NN_UNUSED_VAR(id); 223 #endif // #if DEBUG_PRINT 224 225 if ( m_DebugPrint ) 226 { 227 NN_LOG(" Allocate 0x%x (Physical) (size %d) ", 228 resultAddr, size); 229 230 if (aim == NN_GX_MEM_SYSTEM) 231 { 232 NN_LOG("NN_GX_MEM_SYSTEM"); 233 } 234 else if (aim == NN_GX_MEM_TEXTURE) 235 { 236 NN_LOG("NN_GX_MEM_TEXTURE"); 237 } 238 else if (aim == NN_GX_MEM_VERTEXBUFFER) 239 { 240 NN_LOG("NN_GX_MEM_VERTEXBUFFER"); 241 } 242 else if (aim == NN_GX_MEM_DISPLAYBUFFER) 243 { 244 NN_LOG("NN_GX_MEM_DISPLAYBUFFER"); 245 } 246 else if (aim == NN_GX_MEM_RENDERBUFFER) 247 { 248 NN_LOG("NN_GX_MEM_RENDERBUFFER"); 249 } 250 else if (aim == NN_GX_MEM_COMMANDBUFFER) 251 { 252 NN_LOG("NN_GX_MEM_COMMANDBUFFER"); 253 } 254 255 if ( area == NN_GX_MEM_FCRAM ) 256 { 257 NN_LOG(" FCRAM"); 258 } 259 else if ( area == NN_GX_MEM_VRAMA ) 260 { 261 NN_LOG(" VRAM-A"); 262 } 263 else if ( area == NN_GX_MEM_VRAMB ) 264 { 265 NN_LOG(" VRAM-B"); 266 } 267 268 NN_LOG("\n"); 269 } 270 271 return resultAddr; 272 } 273 274 /* Memory deallocator for DMPGL */ Deallocate(GLenum area,GLenum aim,GLuint id,void * addr)275 void MemoryManager::Deallocate(GLenum area, GLenum aim, GLuint id, void* addr) 276 { 277 NN_UNUSED_VAR(aim); 278 NN_UNUSED_VAR(id); 279 280 if (! m_Initialized) 281 { 282 NN_TPANIC_("Not initialized.\n"); 283 } 284 285 #if DEBUG_PRINT 286 NN_TLOG_("[demo::MemoryManager] (id %d) was deallocated at 0x%08X on %X\n", id, addr, area); 287 #endif 288 289 switch (area) 290 { 291 case NN_GX_MEM_FCRAM: 292 m_HeapOnFcram.Free(addr); 293 break; 294 295 case NN_GX_MEM_VRAMA: 296 case NN_GX_MEM_VRAMB: 297 // Because the buffer in VRAM is simple, do not deallocate 298 break; 299 300 default: 301 NN_TPANIC_("Invalid parameter.\n"); 302 break; 303 } 304 } 305 } 306 307 namespace 308 { 309 demo::memory_manager::detail::MemoryManager s_MemoryManager; 310 } 311 InitializeMemoryManager(const uptr fcramAddress,const size_t memorySize)312 void InitializeMemoryManager(const uptr fcramAddress, const size_t memorySize) 313 { 314 s_MemoryManager.Initialize(fcramAddress, memorySize); 315 } 316 FinalizeMemoryManager(void)317 void FinalizeMemoryManager(void) 318 { 319 s_MemoryManager.Finalize(); 320 } 321 PrintMemoryManagerInfo(void)322 void PrintMemoryManagerInfo(void) 323 { 324 s_MemoryManager.PrintFreeMemorySize(); 325 } 326 GetAllocator(GLenum area,GLenum aim,GLuint id,GLsizei size)327 void* GetAllocator(GLenum area, GLenum aim, GLuint id, GLsizei size) 328 { 329 return s_MemoryManager.Allocate(area, aim, id, size); 330 } 331 GetDeallocator(GLenum area,GLenum aim,GLuint id,void * addr)332 void GetDeallocator(GLenum area, GLenum aim, GLuint id, void* addr) 333 { 334 s_MemoryManager.Deallocate(area, aim, id, addr); 335 } 336 Alloc(size_t size)337 void* Alloc(size_t size) 338 { 339 return s_MemoryManager.Allocate(NN_GX_MEM_FCRAM, NN_GX_MEM_SYSTEM, 0, size); 340 } 341 Alloc(GLenum aim,const size_t size)342 void* Alloc(GLenum aim, const size_t size) 343 { 344 return s_MemoryManager.Allocate(NN_GX_MEM_FCRAM, aim, 0, size); 345 } 346 Alloc(GLenum area,GLenum aim,const size_t size)347 void* Alloc(GLenum area, GLenum aim, const size_t size) 348 { 349 return s_MemoryManager.Allocate(area, aim, 0, size); 350 } 351 Free(void * ptr)352 void Free(void* ptr) 353 { 354 s_MemoryManager.Deallocate(NN_GX_MEM_FCRAM, NN_GX_MEM_SYSTEM, 0, ptr); 355 } 356 } 357 } 358