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