1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: demo_CommandCache.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: 46365 $ 14 *---------------------------------------------------------------------------*/ 15 16 #include "demo/CommandCache/demo_CommandCache.h" 17 18 namespace demo 19 { 20 21 namespace detail 22 { VertexShaderUniformMatrix(void)23 VertexShaderUniformMatrix::VertexShaderUniformMatrix(void) : 24 m_Valid(false), 25 m_RegisterIndex(0) 26 { 27 for (u32 i = 0; i < 4; i++) 28 { 29 for (u32 j = 0; j < 4; j++) 30 { 31 m_Offset[i][j] = 0; 32 } 33 } 34 } 35 ~VertexShaderUniformMatrix()36 VertexShaderUniformMatrix::~VertexShaderUniformMatrix() 37 { 38 } 39 Initialize(void)40 void VertexShaderUniformMatrix::Initialize(void) 41 { 42 m_Valid = false; 43 m_RegisterIndex = 0; 44 for (u32 i = 0; i < 4; i++) 45 { 46 for (u32 j = 0; j < 4; j++) 47 { 48 m_Offset[i][j] = 0; 49 } 50 } 51 } 52 Finalize(void)53 void VertexShaderUniformMatrix::Finalize(void) 54 { 55 } 56 } 57 58 /* ------------------------------------------------------------------------ 59 CommandCache class member functions 60 ------------------------------------------------------------------------ */ 61 CommandCache(void)62 CommandCache::CommandCache(void) : 63 m_State(COMMAND_CACHE_UNINITIALIZED), 64 m_CommandListSize(0x100000), m_CommandListRequestNum(32), 65 m_CopyCommandBuffer(GL_TRUE), m_StateMask(0), 66 m_TotalModelNum(0), m_ModelIndex(0), 67 m_CurrentCommandListId(0), 68 m_CommandListId(0), 69 m_CommandBufferOffset(0), 70 m_CommandBufferSize(0), 71 m_CommandRequestBeginId(0), m_CommandRequestSize(0), 72 m_CommandBufferAddr(NULL) 73 { 74 for (u32 modelIndex = 0; modelIndex < DEMO_MAX_COMMAND_CACHE_MODELS_NUM; modelIndex++) 75 { 76 m_CommandBufferStartOffsetArray[modelIndex] = 0; 77 78 for (u32 matrixIndex = 0; matrixIndex < DEMO_MAX_COMMAND_CACHE_MATRIX_NUM; matrixIndex++) 79 { 80 m_VertexShaderUniformMatrixArray2d[modelIndex][matrixIndex].Initialize(); 81 } 82 } 83 } 84 ~CommandCache()85 CommandCache::~CommandCache() 86 { 87 CommandCache::Finalize(); 88 } 89 Initialize(const u32 CommandListSize,const u32 RequestNum,const GLboolean copyCommandBuffer,const GLbitfield stateMask,const u32 totalModelNum)90 void CommandCache::Initialize(const u32 CommandListSize, const u32 RequestNum, 91 const GLboolean copyCommandBuffer, const GLbitfield stateMask, 92 const u32 totalModelNum) 93 { 94 if ( totalModelNum >= DEMO_MAX_COMMAND_CACHE_MODELS_NUM ) 95 { 96 NN_TPANIC_("totalModelNum(%d) is too large. (Max = %d)\n", 97 totalModelNum, DEMO_MAX_COMMAND_CACHE_MODELS_NUM); 98 } 99 100 m_ModelIndex = 0; 101 102 m_CommandListSize = CommandListSize; 103 m_CommandListRequestNum = RequestNum; 104 m_TotalModelNum = totalModelNum; 105 m_CopyCommandBuffer = copyCommandBuffer; 106 m_StateMask = stateMask; 107 108 m_State = COMMAND_CACHE_INITIALIZED; 109 } 110 Finalize(void)111 void CommandCache::Finalize(void) 112 { 113 DEMO_ASSERT_GL_ERROR(); 114 115 if ( m_CommandListId != 0 ) 116 { 117 nngxDeleteCmdlists(1, &m_CommandListId); 118 m_CommandListId = 0; 119 120 DEMO_ASSERT_GL_ERROR(); 121 } 122 123 for (u32 modelIndex = 0; modelIndex < DEMO_MAX_COMMAND_CACHE_MODELS_NUM; modelIndex++) 124 { 125 m_CommandBufferStartOffsetArray[modelIndex] = 0; 126 127 for (u32 matrixIndex = 0; matrixIndex < DEMO_MAX_COMMAND_CACHE_MATRIX_NUM; matrixIndex++) 128 { 129 m_VertexShaderUniformMatrixArray2d[modelIndex][matrixIndex].Initialize(); 130 } 131 } 132 133 m_State = COMMAND_CACHE_FINALIZED; 134 } 135 SetVSUniformMatrixRegisterIndex(const u32 modelIndex,const u32 uniformMatrixIndex,const u32 registerIndex)136 void CommandCache::SetVSUniformMatrixRegisterIndex(const u32 modelIndex, 137 const u32 uniformMatrixIndex, const u32 registerIndex) 138 { 139 if (! ( modelIndex < m_TotalModelNum )) 140 { 141 NN_TPANIC_("modelIndex(%d) must be < m_TotalModelNum(%d).\n", 142 modelIndex, m_TotalModelNum); 143 } 144 145 if (! ( uniformMatrixIndex < DEMO_MAX_COMMAND_CACHE_MATRIX_NUM ) ) 146 { 147 NN_TPANIC_("uniformMatrixIndex(%d) must be < DEMO_MAX_COMMAND_CACHE_MATRIX_NUM(%d).\n", 148 uniformMatrixIndex, DEMO_MAX_COMMAND_CACHE_MATRIX_NUM); 149 } 150 151 m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_Valid = true; 152 m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_RegisterIndex = registerIndex; 153 } 154 BeginSave(void)155 void CommandCache::BeginSave(void) 156 { 157 if ( m_State != COMMAND_CACHE_INITIALIZED ) 158 { 159 NN_TPANIC_("m_State != COMMAND_CACHE_INITIALIZED.\n"); 160 } 161 162 DEMO_ASSERT_GL_ERROR(); 163 164 // Saves ID of the command list currently bound. 165 nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, (GLint*)&m_CurrentCommandListId); 166 167 // Allocates command list at the save destination. 168 nngxGenCmdlists(1, &m_CommandListId); 169 nngxBindCmdlist(m_CommandListId); 170 nngxCmdlistStorage(m_CommandListSize, m_CommandListRequestNum); 171 172 // Starts saving the command list. 173 nngxStartCmdlistSave(); 174 175 m_State = COMMAND_CACHE_BEGIN_SAVE; 176 177 DEMO_ASSERT_GL_ERROR(); 178 } 179 SaveCommandBufferStartOffset(const u32 modelIndex)180 void CommandCache::SaveCommandBufferStartOffset(const u32 modelIndex) 181 { 182 if ( m_State != COMMAND_CACHE_BEGIN_SAVE ) 183 { 184 NN_TPANIC_("m_State != COMMAND_CACHE_BEGIN_SAVE.\n"); 185 } 186 187 if ( modelIndex < m_TotalModelNum ) 188 { 189 nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, 190 &m_CommandBufferStartOffsetArray[m_ModelIndex]); 191 m_ModelIndex += 1; 192 } 193 else 194 { 195 NN_TPANIC_("modelIndex(%d) must be < m_TotalModelNum(%d)\n", 196 modelIndex, m_TotalModelNum); 197 } 198 } 199 EndSave(void)200 void CommandCache::EndSave(void) 201 { 202 DEMO_ASSERT_GL_ERROR(); 203 204 if ( m_State != COMMAND_CACHE_BEGIN_SAVE ) 205 { 206 NN_TPANIC_("m_State != COMMAND_CACHE_BEGIN_SAVE.\n"); 207 } 208 209 if ( m_ModelIndex == 0 ) 210 { 211 NN_TPANIC_("SaveCommandBufferStartOffset() must be called more than once.\n"); 212 } 213 214 if (! m_CopyCommandBuffer ) 215 { 216 nngxSplitDrawCmdlist(); 217 } 218 219 DEMO_ASSERT_GL_ERROR(); 220 221 // Ends saving the command list. 222 nngxStopCmdlistSave(&m_CommandBufferOffset, &m_CommandBufferSize, 223 &m_CommandRequestBeginId, &m_CommandRequestSize); 224 225 DEMO_ASSERT_GL_ERROR(); 226 227 // Gets the start address of the 3D command buffer of the save destination command list. 228 nngxGetCmdlistParameteri(NN_GX_CMDLIST_TOP_BUFADDR, (GLint*)&m_CommandBufferAddr); 229 // Add the byte offset for the save start address to it. 230 m_CommandBufferAddr += m_CommandBufferOffset; 231 232 DEMO_ASSERT_GL_ERROR(); 233 234 for (u32 modelIndex = 0; modelIndex < m_TotalModelNum; modelIndex++) 235 { 236 // Gets the matrix offset value for the 3D command buffer of the save destination command list. 237 for (u32 uniformMatrixIndex = 0; uniformMatrixIndex < DEMO_MAX_COMMAND_CACHE_MATRIX_NUM; uniformMatrixIndex++) 238 { 239 if ( m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_Valid ) 240 { 241 for (u32 index = 0; index < 4; index++) 242 { 243 demo::detail::GetVSUniformOffset(m_CommandBufferAddr, 244 m_CommandBufferStartOffsetArray[modelIndex] - m_CommandBufferOffset, 245 m_CommandBufferSize, 246 m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_RegisterIndex + index, 247 &m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_Offset[index][0]); 248 } 249 } 250 } 251 } 252 253 m_ModelIndex = 0; 254 255 // Bind the command list again. 256 nngxBindCmdlist(m_CurrentCommandListId); 257 258 m_State = COMMAND_CACHE_END_SAVE; 259 260 DEMO_ASSERT_GL_ERROR(); 261 } 262 UpdateVSUniformMatrix(const u32 modelIndex,const u32 uniformMatrixIndex,const nn::math::MTX44 & matrix)263 void CommandCache::UpdateVSUniformMatrix(const u32 modelIndex, const u32 uniformMatrixIndex, const nn::math::MTX44& matrix) 264 { 265 if ( m_State != COMMAND_CACHE_END_SAVE ) 266 { 267 NN_TPANIC_("m_State != COMMAND_CACHE_END_SAVE.\n"); 268 } 269 270 if (! ( modelIndex < m_TotalModelNum )) 271 { 272 NN_TPANIC_("modelIndex(%d) must be < m_TotalModelNum(%d).\n", 273 modelIndex, m_TotalModelNum); 274 } 275 276 if (! (uniformMatrixIndex < DEMO_MAX_COMMAND_CACHE_MATRIX_NUM )) 277 { 278 NN_TPANIC_("uniformMatrixIndex(%d) must be < DEMO_MAX_COMMAND_CACHE_MATRIX_NUM(%d)\n", 279 uniformMatrixIndex, DEMO_MAX_COMMAND_CACHE_MATRIX_NUM); 280 } 281 282 GLfloat matrixArray[16]; 283 for (u32 index = 0; index < 16; index++) 284 { 285 matrixArray[index] = matrix.m[index & 3][index >> 2]; 286 } 287 288 for (u32 index = 0; index < 4; index++) 289 { 290 *(reinterpret_cast<u32*>(&m_CommandBufferAddr[m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_Offset[index][3]])) = 291 *(reinterpret_cast<u32*>(&matrixArray[0 + index])); 292 *(reinterpret_cast<u32*>(&m_CommandBufferAddr[m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_Offset[index][2]])) = 293 *(reinterpret_cast<u32*>(&matrixArray[4 + index])); 294 *(reinterpret_cast<u32*>(&m_CommandBufferAddr[m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_Offset[index][1]])) = 295 *(reinterpret_cast<u32*>(&matrixArray[8 + index])); 296 *(reinterpret_cast<u32*>(&m_CommandBufferAddr[m_VertexShaderUniformMatrixArray2d[modelIndex][uniformMatrixIndex].m_Offset[index][0]])) = 297 *(reinterpret_cast<u32*>(&matrixArray[12 + index])); 298 } 299 } 300 Append(void)301 void CommandCache::Append(void) 302 { 303 DEMO_ASSERT_GL_ERROR(); 304 305 if ( m_State != COMMAND_CACHE_END_SAVE ) 306 { 307 NN_TPANIC_("m_State != COMMAND_CACHE_END_SAVE.\n"); 308 } 309 310 // Adds the saved command list to the current command list. 311 nngxUseSavedCmdlist(m_CommandListId, 312 m_CommandBufferOffset, m_CommandBufferSize, 313 m_CommandRequestBeginId, m_CommandRequestSize, m_StateMask, m_CopyCommandBuffer); 314 315 DEMO_ASSERT_GL_ERROR(); 316 } 317 Print(void)318 void CommandCache::Print(void) 319 { 320 if ( m_State == COMMAND_CACHE_UNINITIALIZED ) 321 { 322 NN_LOG("CommandCache : State = COMMAND_CACHE_UNINITIALIZED\n"); 323 } 324 else if ( m_State == COMMAND_CACHE_INITIALIZED ) 325 { 326 NN_LOG("CommandCache : State = COMMAND_CACHE_INITIALIZED\n"); 327 } 328 else if ( m_State == COMMAND_CACHE_FINALIZED ) 329 { 330 NN_LOG("CommandCache : State = COMMAND_CACHE_FINALIZED\n"); 331 } 332 else if ( m_State == COMMAND_CACHE_BEGIN_SAVE ) 333 { 334 NN_LOG("CommandCache : State = COMMAND_CACHE_BEGIN_SAVE\n"); 335 } 336 else if ( m_State == COMMAND_CACHE_END_SAVE ) 337 { 338 NN_LOG("CommandCache : State = COMMAND_CACHE_END_SAVE \n"); 339 } 340 341 NN_LOG(" commandListId = %d\n", m_CommandListId); 342 if ( m_CopyCommandBuffer ) 343 { 344 NN_LOG(" Copy 3d command buffer\n"); 345 } 346 else 347 { 348 NN_LOG(" Refer 3d command buffer\n"); 349 } 350 NN_LOG(" bufferOffset = %d, bufferSize = %d\n", m_CommandBufferOffset, m_CommandBufferSize); 351 NN_LOG(" requestBeginId = %d, requestSize = %d\n", m_CommandRequestBeginId, m_CommandRequestSize); 352 NN_LOG(" modelIndex = %d, totalModelNum = %d\n", m_ModelIndex, m_TotalModelNum); 353 } 354 355 namespace detail 356 { GetVSUniformOffset(u8 * bufferAddress,const u32 startOffset,const GLsizei bufferSize,const u32 uniformFloatRegIndex,u32 * uniformOffsetArray)357 void GetVSUniformOffset(u8* bufferAddress, const u32 startOffset, 358 const GLsizei bufferSize, const u32 uniformFloatRegIndex, u32* uniformOffsetArray) 359 { 360 u32 const_current_addr = 0xffffffff; 361 u32 const_current_index = 0; 362 u32 const_f32_mode = 0; 363 364 for (u32 i = 0; i < 4; i++) 365 { 366 uniformOffsetArray[i] = 0xffffffff; 367 } 368 369 for (u32 offset = startOffset; offset < bufferSize; ) 370 { 371 CommandBuffer3d* command; 372 command = (CommandBuffer3d*)&bufferAddress[offset]; 373 374 if ( command->size == 0 ) 375 { 376 // single command 377 if ( command->be ) 378 { 379 if ( command->addr == VS_UNIFORM_FLOAT_REG_INDEX ) 380 { 381 const_current_addr = command->data & 0xff; 382 const_current_index = 0; 383 const_f32_mode = (command->data & 0x80000000); 384 } 385 else if ( (command->addr >= VS_UNIFORM_FLOAT_REG_VALUE_BEGIN) && (command->addr <= VS_UNIFORM_FLOAT_REG_VALUE_END) ) 386 { 387 if (const_current_addr == uniformFloatRegIndex) 388 { 389 uniformOffsetArray[const_current_index] = offset; 390 if (const_current_index == 3) 391 { 392 break; 393 } 394 } 395 396 ++const_current_index; 397 if (const_f32_mode ? (const_current_index == 4) : (const_current_index == 3)) 398 { 399 const_current_addr++; 400 const_current_index = 0; 401 } 402 } 403 } 404 offset += 8; 405 } 406 else 407 { 408 // burst command 409 if (command->be) 410 { 411 if (command->seq) 412 { 413 // sequencial mode 414 if (!((VS_UNIFORM_FLOAT_REG_INDEX > command->addr + command->size) || command->addr > VS_UNIFORM_FLOAT_REG_VALUE_END)) 415 { 416 u32 i = 0; 417 for (i = 0; i < command->size + 1; i++) 418 { 419 unsigned addr = command->addr + i; 420 if (addr == VS_UNIFORM_FLOAT_REG_INDEX) 421 { 422 const_current_addr = ((i == 0) ? command->data : bufferAddress[offset + 4 + 4 * i]) & 0xff; 423 const_current_index = 0; 424 const_f32_mode = (((i == 0) ? command->data : bufferAddress[offset + 4 + 4 * i]) & 0x80000000); 425 } 426 else if ( (addr >= VS_UNIFORM_FLOAT_REG_VALUE_BEGIN) && (addr <= VS_UNIFORM_FLOAT_REG_VALUE_END) ) 427 { 428 if (const_current_addr == uniformFloatRegIndex) 429 { 430 uniformOffsetArray[const_current_index] = (i == 0) ? offset : (offset + 4 + 4 * i); 431 if (const_current_index == 3) 432 { 433 break; 434 } 435 } 436 ++const_current_index; 437 if (const_f32_mode ? (const_current_index == 4) : (const_current_index == 3)) 438 { 439 const_current_addr++; 440 const_current_index = 0; 441 } 442 } 443 } 444 if (i != command->size + 1) 445 { 446 break; 447 } 448 } 449 } 450 else 451 { 452 // non sequencial mode 453 if (command->addr == VS_UNIFORM_FLOAT_REG_INDEX) 454 { 455 const_current_addr = (bufferAddress[offset + 4 + 4 * command->size]) & 0xff; 456 const_current_index = 0; 457 const_f32_mode = (bufferAddress[offset + 4 + 4 * command->size] & 0x80000000); 458 } 459 else if (command->addr >= VS_UNIFORM_FLOAT_REG_VALUE_BEGIN && command->addr <= VS_UNIFORM_FLOAT_REG_VALUE_END) 460 { 461 u32 i = 0; 462 for (i = 0; i < command->size + 1; i++) 463 { 464 if (const_current_addr == uniformFloatRegIndex) 465 { 466 uniformOffsetArray[const_current_index] = (i == 0) ? offset : (offset + 4 + 4 * i); 467 if (const_current_index == 3) 468 { 469 break; 470 } 471 } 472 ++const_current_index; 473 if (const_f32_mode ? (const_current_index == 4) : (const_current_index == 3)) 474 { 475 const_current_addr++; 476 const_current_index = 0; 477 } 478 } 479 480 if (i != command->size + 1) 481 { 482 break; 483 } 484 } 485 } 486 } 487 offset += (command->size + 1) * 4 + 4; 488 if (offset & 4) 489 { 490 offset += 4; 491 } 492 } 493 } 494 } 495 } 496 PrintCurrentCmdlist(void)497 void PrintCurrentCmdlist(void) 498 { 499 GLint bufferSize = 0; 500 nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, &bufferSize); 501 502 GLint maxBufferSize = 0; 503 nngxGetCmdlistParameteri(NN_GX_CMDLIST_MAX_BUFSIZE, &maxBufferSize); 504 505 GLint reqCount = 0; 506 nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_REQCOUNT, &reqCount); 507 508 GLint maxReqCount = 0; 509 nngxGetCmdlistParameteri(NN_GX_CMDLIST_MAX_REQCOUNT, &maxReqCount); 510 511 NN_LOG("CommandList information\n"); 512 NN_LOG(" bufferSize = %d/%d\n", bufferSize, maxBufferSize); 513 NN_LOG(" reqCount = %d/%d\n", reqCount, maxReqCount); 514 } 515 516 } 517