1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: gr_Shader.cpp 4 5 Copyright (C)2010 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: 33699 $ 14 *---------------------------------------------------------------------------*/ 15 16 #include <nn/gr/CTR/gr_Shader.h> 17 18 namespace nn 19 { 20 namespace gr 21 { 22 namespace CTR 23 { Shader(void)24 Shader::Shader( void ) : 25 m_VtxShaderIndex( 0 ), m_GeoShaderIndex( - 1 ), 26 m_ExeImageInfoNum( 0 ), 27 m_InstructionCount( 0 ), m_SwizzleCount( 0 ), 28 m_DrawMode( PICA_DATA_DRAW_TRIANGLES ), 29 m_VtxShaderBoolMapUniform( 0 ), m_GeoShaderBoolMapUniform( 0 ), 30 m_CmdCacheOutAttrNum( 0 ), 31 m_CmdCacheVtxConstNum( 0 ), m_CmdCacheGeoConstNum( 0 ) 32 { 33 for ( u32 index = 0; index < OUT_ATTR_COMMAND_MAX; index++) 34 { 35 m_CmdCacheOutAttr[ index ] = 0; 36 } 37 38 for ( u32 index = 0; index < CONST_REG_COMMAND_MAX; index++) 39 { 40 m_CmdCacheVtxConst[ index ] = 0; 41 m_CmdCacheGeoConst[ index ] = 0; 42 } 43 } 44 SetupBinary(const void * shader_binary,const int vtx_shader_index,const int geo_shader_index)45 void Shader::SetupBinary( const void* shader_binary, const int vtx_shader_index, const int geo_shader_index ) 46 { 47 const bit32* binary = reinterpret_cast< const bit32* >( shader_binary ); 48 NN_GR_ASSERT( binary != NULL ); 49 50 NN_GR_ASSERT( *binary == 0x424C5644 ); // DVLB 51 ++binary; 52 53 NN_GR_ASSERT( *binary < EXE_IMAGE_MAX ); 54 m_ExeImageInfoNum = *binary; 55 ++binary; 56 57 m_VtxShaderIndex = vtx_shader_index; 58 m_GeoShaderIndex = geo_shader_index; 59 m_VtxShaderBoolMapUniform = 0; 60 m_GeoShaderBoolMapUniform = 0; 61 62 for ( int i = 0; i < m_ExeImageInfoNum; ++i ) 63 { 64 m_ExeImageInfo[ i ] = reinterpret_cast< const ExeImageInfo* >( (u8*)shader_binary + *binary ); 65 NN_GR_ASSERT( m_ExeImageInfo[ i ]->signature == 0x454c5644 ); // DVLP 66 ++binary; 67 } 68 69 const bit32* package_info = binary; 70 NN_GR_ASSERT( *binary == 0x504C5644 ); // DVLP 71 ++binary; 72 ++binary; 73 74 m_Instruction = reinterpret_cast< const bit32* >( (u8*)package_info + *binary ); 75 ++binary; 76 77 m_InstructionCount = *binary; 78 ++binary; 79 80 const bit32* swizzle = reinterpret_cast< const bit32* >( (u8*)package_info + *binary ); 81 ++binary; 82 83 m_SwizzleCount = *binary; 84 NN_GR_ASSERT( m_SwizzleCount < SWIZZLE_PATTERN_MAX ); 85 ++binary; 86 87 for ( int i = 0; i < m_SwizzleCount; i++ ) 88 { 89 m_Swizzle[ i ] = swizzle[ i * 2 ] ; 90 } 91 // 範囲テスト 92 NN_GR_ASSERT( 0 <= m_VtxShaderIndex && m_VtxShaderIndex < m_ExeImageInfoNum ); 93 94 // バイナリとの整合性のテスト 95 NN_GR_ASSERT( !m_ExeImageInfo[ m_VtxShaderIndex ]->isGeoShader ); 96 97 if ( IsEnableGeoShader() ) 98 { 99 // 範囲テスト 100 NN_GR_ASSERT( m_GeoShaderIndex < GetShaderNum() ); 101 102 // バイナリとの整合性のテスト 103 NN_GR_ASSERT( m_ExeImageInfo[ m_GeoShaderIndex ]->isGeoShader ); 104 105 // 定数レジスタのコマンド生成 106 m_CmdCacheGeoConstNum = MakeConstRgCommand_( m_CmdCacheGeoConst, true ) - m_CmdCacheGeoConst; 107 NN_GR_ASSERT( m_CmdCacheGeoConstNum <= CONST_REG_COMMAND_MAX ); 108 } 109 110 // 定数レジスタのコマンド生成 111 m_CmdCacheVtxConstNum = MakeConstRgCommand_( m_CmdCacheVtxConst, false ) - m_CmdCacheVtxConst; 112 NN_GR_ASSERT( m_CmdCacheVtxConstNum <= CONST_REG_COMMAND_MAX ); 113 114 // 出力属性のコマンド生成 115 m_CmdCacheOutAttrNum = MakeOutAttrCommand_( m_CmdCacheOutAttr ) - m_CmdCacheOutAttr; 116 NN_GR_ASSERT( m_CmdCacheOutAttrNum <= OUT_ATTR_COMMAND_MAX ); 117 } 118 119 //------------------------------------------------------------------------ 120 MakeFullCommand(bit32 * command) const121 bit32* Shader::MakeFullCommand( bit32* command ) const 122 { 123 { // ジオメトリシェーダー使用設定コマンドなどの生成 124 command = MakePrepareCommand( command ); 125 } 126 127 if ( IsEnableGeoShader() ) 128 { // ジオメトリシェーダー 129 command = MakeGeoProgramCommand( command ); 130 command = MakeGeoSwizzleCommand( command ); 131 command = MakeGeoConstRgCommand( command ); 132 command = MakeGeoBoolMapCommand( command ); 133 } 134 135 { // 頂点シェーダー 136 command = MakeVtxProgramCommand( command ); 137 command = MakeVtxSwizzleCommand( command ); 138 command = MakeVtxConstRgCommand( command ); 139 command = MakeVtxBoolMapCommand( command ); 140 } 141 142 { // 出力属性(outmap)関連 143 command = MakeOutAttrCommand( command ); 144 } 145 146 return command; 147 } 148 149 //------------------------------------------------------------------------ 150 MakeDisableCommand(bit32 * command)151 bit32* Shader::MakeDisableCommand( bit32* command ) 152 { 153 const bool isEnableGeometryShader = false; 154 const PicaDataDrawMode drawMode = PICA_DATA_DRAW_TRIANGLES; 155 156 command = MakeShaderModeCommand_( command, 157 isEnableGeometryShader, 158 drawMode ); 159 160 return command; 161 } 162 163 //------------------------------------------------------------------------ 164 MakePrepareCommand(bit32 * command) const165 bit32* Shader::MakePrepareCommand( bit32* command ) const 166 { 167 bool isEnableGeoShader = IsEnableGeoShader(); 168 PicaDataDrawMode drawMode = m_DrawMode; 169 170 command = 171 MakeShaderModeCommand_( command, 172 isEnableGeoShader, 173 drawMode ); 174 175 return command; 176 } 177 178 //------------------------------------------------------------------------ 179 MakeVtxProgramCommand(bit32 * command) const180 bit32* Shader::MakeVtxProgramCommand( bit32* command ) const 181 { 182 int shader_index = GetVtxShaderIndex(); 183 bit32 reg_addr = PICA_REG_VS_PROG_ADDR; // 0x2cb 184 bit32 reg_load = PICA_REG_VS_PROG_DATA0; // 0x2cc 185 bit32 reg_end = PICA_REG_VS_PROG_UPDATE_END; // 0x2bf 186 187 { // プログラムコードのロードアドレスを設定 188 *command++ = 0; 189 *command++ = PICA_CMD_HEADER_SINGLE( reg_addr ); 190 } 191 192 { // プログラムコードのロード 193 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 194 195 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 196 197 NN_UNUSED_VAR( exe_info ); 198 199 u32 instructionCount = m_InstructionCount; 200 if ( instructionCount > 512 ) 201 { 202 instructionCount = 512; 203 } 204 205 command = MakeLoadCommand_( command, reg_load, 206 m_Instruction, 207 m_InstructionCount < 512 ? m_InstructionCount : 512 ); 208 } 209 210 { // プログラム更新の完了通知 211 *command++ = 1; 212 *command++ = PICA_CMD_HEADER_SINGLE( reg_end ); 213 } 214 215 return command; 216 } 217 218 //------------------------------------------------------------------------ 219 MakeGeoProgramCommand(bit32 * command) const220 bit32* Shader::MakeGeoProgramCommand( bit32* command ) const 221 { 222 int shader_index = GetGeoShaderIndex(); 223 bit32 reg_addr = PICA_REG_GS_PROG_ADDR; // 0x29b 224 bit32 reg_load = PICA_REG_GS_PROG_DATA0; // 0x29c 225 bit32 reg_end = PICA_REG_GS_PROG_UPDATE_END; // 0x28f 226 227 { // プログラムコードのロードアドレスを設定 228 *command++ = 0; 229 *command++ = PICA_CMD_HEADER_SINGLE( reg_addr ); 230 } 231 232 { // プログラムコードのロード 233 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 234 235 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 236 237 NN_UNUSED_VAR( exe_info ); 238 239 command = MakeLoadCommand_( command, reg_load, 240 m_Instruction, 241 m_InstructionCount ); 242 } 243 244 { // プログラム更新の完了通知 245 *command++ = 1; 246 *command++ = PICA_CMD_HEADER_SINGLE( reg_end ); 247 } 248 249 return command; 250 } 251 252 //------------------------------------------------------------------------ 253 MakeShaderModeCommand_(bit32 * command,const bool isEnableGeoShader,const PicaDataDrawMode drawMode)254 bit32* Shader::MakeShaderModeCommand_( bit32* command, 255 const bool isEnableGeoShader, 256 const PicaDataDrawMode drawMode ) 257 { 258 // 0x25e[9:8] への設定 259 { 260 if ( isEnableGeoShader ) 261 { 262 *command++ = PICA_DATA_DRAW_GEOMETRY_PRIMITIVE << 8; 263 } 264 else 265 { 266 *command++ = drawMode << 8; 267 } 268 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 2 ); 269 } 270 271 // 0x251 へのダミーコマンド 272 { 273 command = MakeDummyCommand_( command, PICA_REG_VS_OUT_REG_NUM2, DUMMY_DATA_NUM_251 ); 274 } 275 276 // 0x200 へのダミーコマンド 277 { 278 command = MakeDummyCommand_( command, PICA_REG_VERTEX_ATTR_ARRAYS_BASE_ADDR, DUMMY_DATA_NUM_200 ); 279 } 280 281 // 0x229[1:0] ジオメトリシェーダーの有効、無効を設定 282 { 283 *command++ = isEnableGeoShader ? 2 : 0; 284 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 1 ); 285 } 286 287 // 0x200 へのダミーコマンド 288 { 289 command = MakeDummyCommand_( command, PICA_REG_VERTEX_ATTR_ARRAYS_BASE_ADDR, DUMMY_DATA_NUM_200 ); 290 } 291 292 // 0x244 ジオメトリシェーダーの設定を頂点シェーダーと共有するかどうか 293 { 294 *command++ = isEnableGeoShader ? 1 : 0; 295 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_COM_MODE, 1 ); 296 } 297 298 return command; 299 } 300 301 //------------------------------------------------------------------------ 302 MakeConstRgCommand_(bit32 * command,const bool is_geometry_shader)303 bit32* Shader::MakeConstRgCommand_( bit32* command, 304 const bool is_geometry_shader ) 305 { 306 int shader_index = GetVtxShaderIndex(); 307 bit32 reg_float = PICA_REG_VS_FLOAT_ADDR; // 0x2c0 308 bit32 reg_integer = PICA_REG_VS_INT0; // 0x2b1 309 bit32* boolMap = &m_VtxShaderBoolMapUniform; 310 311 if ( is_geometry_shader ) 312 { 313 shader_index = GetGeoShaderIndex(); 314 reg_float = PICA_REG_GS_FLOAT_ADDR; // 0x290 315 reg_integer = PICA_REG_GS_INT0; // 0x281 316 boolMap = &m_GeoShaderBoolMapUniform; 317 } 318 319 // プログラム情報 320 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 321 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 322 323 // 定数レジスタ情報 324 struct SetupInfo { u16 type; u16 index; bit32 value[4]; }; 325 326 const SetupInfo* setupInfo = 327 reinterpret_cast< const SetupInfo* >( 328 reinterpret_cast< const u8* >( exe_info ) + exe_info->setupOffset ); 329 330 // 定数レジスタのコマンド生成 331 for ( int i = 0; i < exe_info->setupCount; ++i ) 332 { 333 const SetupInfo& info = setupInfo[ i ]; 334 const bit32* value = info.value; 335 336 switch ( info.type ) 337 { 338 case 0 : // bool register setup 339 *boolMap |= ( info.value[ 0 ] << info.index ) & ( 1 << info.index ); 340 break; 341 342 case 1 : // integer register setup 343 *command++ = value[ 0 ] | value[ 1 ] << 8 | value[ 2 ] << 16 | value[ 3 ] << 24; 344 *command++ = PICA_CMD_HEADER_SINGLE( reg_integer + info.index ); 345 break; 346 347 case 2 : // float register setup 348 *command++ = info.index; 349 *command++ = PICA_CMD_HEADER_BURSTSEQ( reg_float, 4 ); 350 *command++ = ( value[ 3 ] << 8 & 0xffffff00 ) | ( value[ 2 ] >> 16 & 0x000000ff ); 351 *command++ = ( value[ 2 ] << 16 & 0xffff0000 ) | ( value[ 1 ] >> 8 & 0x0000ffff ); 352 *command++ = ( value[ 1 ] << 24 & 0xff000000 ) | ( value[ 0 ] >> 0 & 0x00ffffff ); 353 *command++ = PADDING_DATA; // padding 354 break; 355 } 356 } 357 358 return command; 359 } 360 361 //------------------------------------------------------------------------ 362 MakeOutAttrCommand_(bit32 * command)363 bit32* Shader::MakeOutAttrCommand_( bit32* command ) 364 { 365 // 出力属性の設定 366 // ジオメトリシェーダーが有効な場合、 367 // 出力属性は、ジオメトリシェーダーについて設定をおこなう 368 const int shader_index = IsEnableGeoShader() ? GetGeoShaderIndex() : GetVtxShaderIndex(); 369 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 370 371 enum 372 { 373 OUT_ATTR_INDEX_MAX = 7, 374 OUT_ATTR_DIMENTION_MAX = 4, 375 OUT_ATTR_BUFFER_MAX = 16 * 4, 376 VS_OUT_ATTR_INDEX_MAX = 16 377 }; 378 379 // 出力属性情報 380 struct OutmapInfo { u16 type; u16 index; u16 mask; u16 reserve; }; 381 382 u32 outNum = 0; 383 bit32 useTex = 0; 384 bit32 clock = 0; 385 bit32 outMask = 0; 386 bit32 attr[ OUT_ATTR_INDEX_MAX ]; 387 388 { // 出力属性の設定をもとめる 389 390 // プログラム情報 391 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 392 393 394 // 実際の出力属性情報. 395 OutmapInfo outmap_buffer[ OUT_ATTR_BUFFER_MAX ]; 396 s32 outMapBufferCount = 0; 397 398 // マージ. 399 if ( IsEnableGeoShader() && exe_info->outputMaps ) 400 { 401 bit32 gs_copy_mask = 0; 402 bit32 vs_copy_mask = 0; 403 // GS出力属性情報 404 const OutmapInfo* outmapInfo = 405 reinterpret_cast< const OutmapInfo* >( 406 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset ); 407 // VSプログラム情報 408 int vtx_shader_index = GetVtxShaderIndex(); 409 NN_GR_ASSERT( 0 <= vtx_shader_index && vtx_shader_index < m_ExeImageInfoNum ); 410 const ExeImageInfo* vtx_exe_info = m_ExeImageInfo[ vtx_shader_index ]; 411 412 // VS出力属性情報 413 const OutmapInfo* vtxOutmapInfo = 414 reinterpret_cast< const OutmapInfo* >( 415 reinterpret_cast< const u8* >( vtx_exe_info ) + vtx_exe_info->outMapOffset ); 416 // 最初にVSとGS両方で指定されているものを設定. 417 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX ); 418 for( int g = 0; g < exe_info->outMapCount; ++g ) 419 { 420 for( int v = 0; v < vtx_exe_info->outMapCount; ++v ) 421 { 422 if ( outmapInfo[ g ].type == vtxOutmapInfo[ v ].type ) 423 { 424 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_INDEX_MAX ); 425 outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type; 426 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount; 427 outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask; 428 gs_copy_mask |= 1 << g; 429 vs_copy_mask |= 1 << v; 430 ++outMapBufferCount; 431 } 432 } 433 } 434 // 次にGSのみで定義されているものを設定. 435 for( int g = 0; g < exe_info->outMapCount; ++g ) 436 { 437 if ( !( gs_copy_mask & ( 1 << g ) ) && ( outmapInfo[ g ].type >= 0 && outmapInfo[ g ].type < 9 && outmapInfo[ g ].type != 7 ) ) 438 { 439 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX ); 440 outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type; 441 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount; 442 outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask; 443 ++outMapBufferCount; 444 } 445 } 446 // 最後ににVSのみで定義されているものを設定. 447 for( int v = 0; v < vtx_exe_info->outMapCount; ++v ) 448 { 449 if ( !( vs_copy_mask & ( 1 << v ) ) && 450 ( vtxOutmapInfo[ v ].type >= 0 && vtxOutmapInfo[ v ].type < 9 && vtxOutmapInfo[ v ].type != 7 ) ) 451 { 452 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX ); 453 outmap_buffer[ outMapBufferCount ].type = vtxOutmapInfo[ v ].type; 454 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount; 455 outmap_buffer[ outMapBufferCount ].mask = vtxOutmapInfo[ v ].mask; 456 ++outMapBufferCount; 457 } 458 } 459 } 460 else 461 { 462 // 出力属性情報 463 const OutmapInfo* outmapInfo = 464 reinterpret_cast< const OutmapInfo* >( 465 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset ); 466 // マージしない場合はコピー. 467 for( int i = 0; i < exe_info->outMapCount; ++i ) 468 { 469 outmap_buffer[ i ] = outmapInfo[ i ]; 470 } 471 outMapBufferCount = exe_info->outMapCount; 472 } 473 474 for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index ) 475 { 476 attr[ index ] = 0x1f1f1f1f; 477 for ( int i = 0; i <outMapBufferCount; ++i ) 478 { 479 bit32 c = 0; 480 for ( int j = 0; outmap_buffer[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j ) 481 { 482 if ( ( outmap_buffer[ i ].mask & ( 1 << j ) ) == 0 ) continue; 483 484 int value = 0x1f; 485 switch ( outmap_buffer[ i ].type ) 486 { 487 case 0 : value = 0x00 + c++; if (c == 2) clock |= 1 << 0; break; // position 488 case 1 : value = 0x04 + c++; clock |= 1 << 24; break; // quaternion 489 case 2 : value = 0x08 + c++; clock |= 1 << 1; break; // color 490 case 3 : if (c < 2) value = 0x0c + c++; useTex = 1; clock |= 1 << 8; break; // texcoord0 491 case 4 : value = 0x10; useTex = 1; clock |= 3 << 16; break; // texcoord0w 492 case 5 : if (c < 2) value = 0x0e + c++; useTex = 1; clock |= 1 << 9; break; // texcoord1 493 case 6 : if (c < 2) value = 0x16 + c++; useTex = 1; clock |= 1 << 10; break; // texcoord2 494 case 8 : if (c < 3) value = 0x12 + c++; clock |= 1 << 24; break; // view 495 } 496 attr[ index ] = attr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 ); 497 } 498 } 499 if ( attr[ index ] != 0x1f1f1f1f ) 500 { 501 outMask |= ( 1 << index ); 502 ++outNum; 503 } 504 } 505 } 506 507 if ( IsEnableGeoShader() ) 508 { 509 // 頂点シェーダーの出力属性の設定をもとめる 510 m_DrawMode = PICA_DATA_DRAW_GEOMETRY_PRIMITIVE; 511 512 u32 vtxOutNum = 0; 513 bit32 vtxOutMask = 0; 514 bit32 vtxAttr[ VS_OUT_ATTR_INDEX_MAX ]; 515 516 // プログラム情報 517 const ExeImageInfo* exe_info = m_ExeImageInfo[ m_VtxShaderIndex ]; 518 const OutmapInfo* outmapInfo = 519 reinterpret_cast< const OutmapInfo* >( 520 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset ); 521 522 for ( int index = 0; index < VS_OUT_ATTR_INDEX_MAX; ++index ) 523 { 524 vtxAttr[ index ] = 0x1f1f1f1f; 525 for ( int i = 0; i < exe_info->outMapCount; ++i ) 526 { 527 u32 c = 0; 528 for ( int j = 0; outmapInfo[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j ) 529 { 530 if ( ( outmapInfo[ i ].mask & ( 1 << j ) ) == 0 ) continue; 531 532 int value = 0x1f; 533 switch ( outmapInfo[ i ].type ) 534 { 535 case 0 : value = 0x00 + c++; break; // position 536 case 1 : value = 0x04 + c++; break; // quaternion 537 case 2 : value = 0x08 + c++; break; // color 538 case 3 : if (c < 2) value = 0x0c + c++; break; // texcoord0 539 case 4 : value = 0x10; break; // texcoord0w 540 case 5 : if (c < 2) value = 0x0e + c++; break; // texcoord1 541 case 6 : if (c < 2) value = 0x16 + c++; break; // texcoord2 542 case 8 : if (c < 3) value = 0x12 + c++; break; // view 543 case 9 : value = 0xff; 544 } 545 vtxAttr[ index ] = vtxAttr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 ); 546 } 547 } 548 if ( vtxAttr[ index ] != 0x1f1f1f1f ) 549 { 550 vtxOutMask |= ( 1 << index ); 551 ++vtxOutNum; 552 } 553 } 554 555 bit32 gsDataMode = m_ExeImageInfo[ m_GeoShaderIndex ]->gsDataMode; 556 557 // GL_GEOMETRY_PRIMITIVE_DMP 558 559 // 0x229 [31:31], 560 // データモード 1 の場合 561 if ( gsDataMode == 1 ) 562 { 563 *command++ = 0x80000000; 564 } 565 // データモード 0 と データモード2 の場合 566 else 567 { 568 *command++ = 0x00000000; 569 } 570 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa ); 571 572 // 0x253 573 *command++ = 0x00000000; 574 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 ); 575 576 // 0x289 頂点シェーダーの出力数 577 *command++ = 0x08000000 | (gsDataMode == 0 ? 0x0000 : 0x0100) | vtxOutNum - 1; 578 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb ); 579 580 // 0x28a ジオメトリシェーダーのmainラベルのアドレス 581 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_GeoShaderIndex ]->mainAddress; 582 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_START_ADDR ); 583 584 // 0x28d 頂点シェーダーの出力mask 585 *command++ = outMask; 586 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_OUT_REG_MASK ); 587 588 // 0x2ba 頂点シェーダーのmainラベルのアドレス 589 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress; 590 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR ); 591 592 // 0x2bd 頂点シェーダーの出力レジスタマスク 593 *command++ = vtxOutMask; 594 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK ); 595 596 // 0x251 頂点シェーダーの出力数 597 *command++ = vtxOutNum - 1; 598 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 ); 599 600 // 0x28b 頂点シェーダーの出力とジオメトリシェーダーの入力は一致させているのが前提 601 *command++ = 0x76543210; 602 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP0 ); // 0x28b 603 604 // 0x28c 605 *command++ = 0xfedcba98; 606 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP1 ); 607 608 // 0x254 609 if ( ( gsDataMode == 1 ) && ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum != 0 ) ) 610 { 611 *command++ = m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1; 612 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_MISC_REG1, 0x1 ); 613 } 614 615 // 0x252 用の値 616 if ( gsDataMode == 2 ) 617 { 618 gsDataMode |= 0x01 << 24; 619 gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexStartIndex ) << 16; 620 gsDataMode |= ( vtxOutNum - 1 ) << 12; 621 gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1 ) << 8; 622 } 623 624 // 0x252 データモードの指定 625 *command++ = gsDataMode; 626 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 ); 627 628 // 0x24a 629 *command++ = vtxOutNum - 1; 630 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 ); 631 } 632 else 633 { 634 // 0x229 [31:31] 635 *command++ = 0x0; 636 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0x8 ); 637 638 // 0x253 [0:0] 639 *command++ = 0x0; 640 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x1 ); 641 642 // 0x289 [31:24], [15:8], [3:0] 頂点シェーダーのモードの設定 643 *command++ = 0xa0000000; 644 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb ); 645 646 // 0x2ba 頂点シェーダーのmainラベルのアドレス 647 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress; 648 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR ); 649 650 // 0x2bd 頂点シェーダーの出力レジスタマスク 651 *command++ = outMask; 652 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK ); 653 654 // 0x251 655 *command++ = outNum - 1; 656 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 ); 657 658 // 0x252 659 *command++ = 0; 660 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 ); 661 662 // 0x24a 663 *command++ = outNum - 1; 664 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 ); 665 } 666 667 { 668 // 0x25e [3:0] 669 *command++ = outNum - 1; 670 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 0x1 ); 671 672 // 0x04f 673 *command++ = outNum; 674 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM0 ); 675 676 // 出力属性のコマンド 677 outNum = 0; 678 for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index ) 679 { 680 if ( attr[ index ] != 0x1f1f1f1f ) 681 { 682 *command++ = attr[ index ]; 683 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + outNum ); 684 ++outNum; 685 } 686 } 687 for ( int index = outNum; index < OUT_ATTR_INDEX_MAX; ++index ) 688 { 689 *command++ = attr[ index ]; 690 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + index ); 691 } 692 } 693 694 // 0x064 テクスチャ座標を使うかどうかを設定 695 *command++ = useTex; 696 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_MODE ); 697 698 // 0x06f 出力属性のクロック制御を設定 699 *command++ = clock; 700 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_CLK ); 701 702 if ( IsEnableGeoShader() ) 703 { 704 // 0x25e 705 *command++ = 0; 706 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 8 ); 707 } 708 709 return command; 710 } 711 712 //------------------------------------------------------------------------ 713 MakeLoadCommand_(bit32 * command,const bit32 load_reg,const bit32 * src_buffer_ptr,const u32 src_data_num) const714 bit32* Shader::MakeLoadCommand_( bit32* command, 715 const bit32 load_reg, 716 const bit32* src_buffer_ptr, 717 const u32 src_data_num ) const 718 { 719 enum { WRITE_MAX = 128 }; 720 721 u32 rest = src_data_num; 722 723 while ( true ) 724 { 725 if ( rest <= WRITE_MAX ) 726 { 727 *command++ = *src_buffer_ptr++; 728 *command++ = PICA_CMD_HEADER_BURST( load_reg, rest ); 729 std::memcpy( command, src_buffer_ptr, ( rest - 1 ) * sizeof( bit32 ) ); 730 command += rest - 1; 731 732 if ( ( rest & 1 ) == 0 ) *command++ = PADDING_DATA; // padding 733 break; 734 } 735 else 736 { 737 *command++ = *src_buffer_ptr++; 738 *command++ = PICA_CMD_HEADER_BURST( load_reg, WRITE_MAX ); 739 std::memcpy( command, src_buffer_ptr, ( WRITE_MAX - 1 ) * sizeof( bit32 ) ); 740 741 command += WRITE_MAX - 1; 742 src_buffer_ptr += WRITE_MAX - 1; 743 744 rest -= WRITE_MAX; 745 if ( ( WRITE_MAX & 1 ) == 0 ) *command++ = PADDING_DATA; // padding 746 } 747 } 748 749 return command; 750 } 751 752 //------------------------------------------------------------------------ 753 MakeDummyCommand_(bit32 * command,const bit32 load_reg,const u32 dataNum)754 bit32* Shader::MakeDummyCommand_( bit32* command, 755 const bit32 load_reg, 756 const u32 dataNum ) 757 { 758 *command++ = 0; 759 *command++ = PICA_CMD_HEADER_BURST_BE( load_reg, dataNum, 0 ); 760 761 for ( int i = 0; i < dataNum - ( dataNum & 1 ); ++i) 762 { 763 *command++ = PADDING_DATA; 764 } 765 766 return command; 767 } 768 769 //------------------------------------------------------------------------ 770 SearchBindSymbol(BindSymbol * symbol,const char * name) const771 bool Shader::SearchBindSymbol( BindSymbol* symbol, 772 const char* name ) const 773 { 774 const int shader_index = ( symbol->shaderType == BindSymbol::SHADER_TYPE_GEOMETRY ) 775 ? GetGeoShaderIndex() : GetVtxShaderIndex(); 776 777 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 778 779 // プログラム情報 780 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 781 782 // シンボル情報 783 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 784 const BindSymbolInfo* bind_symbol_info = 785 reinterpret_cast< const BindSymbolInfo* >( 786 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 787 788 // 文字列情報 789 const char* string = 790 reinterpret_cast< const char* >( 791 reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset ); 792 793 // 検索 794 u32 namelen = std::strlen( name ); 795 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 796 { 797 const BindSymbolInfo& info = bind_symbol_info[ i ]; 798 799 if ( std::strncmp( name, &string[ info.nameIndex ], namelen ) != 0 ) continue; 800 if ( string[ info.nameIndex + namelen ] != '\0' && string[ info.nameIndex + namelen ] != '.' ) continue; 801 802 symbol->name = &string[ info.nameIndex ]; 803 symbol->start = (info.regIndex & 0x0000ffff); 804 symbol->end = (info.regIndex & 0xffff0000) >> 16; 805 806 if ( 136 <= symbol->start ) 807 { 808 return false; 809 } 810 else if ( 120 <= symbol->start ) 811 { 812 symbol->start -= 120; 813 symbol->end -= 120; 814 815 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL; 816 } 817 else if ( 112 <= symbol->start ) 818 { 819 symbol->start -= 112; 820 symbol->end -= 112; 821 822 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER; 823 } 824 else if ( 16 <= symbol->start ) 825 { 826 symbol->start -= 16; 827 symbol->end -= 16; 828 829 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT; 830 } 831 else 832 { 833 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT; 834 } 835 } 836 837 return false; 838 } 839 840 //------------------------------------------------------------------------ 841 SearchBindSymbolNum(const BindSymbol::ShaderType shader_type,const BindSymbol::SymbolType symbol_type) const842 u32 Shader::SearchBindSymbolNum( 843 const BindSymbol::ShaderType shader_type, 844 const BindSymbol::SymbolType symbol_type ) const 845 { 846 const int shader_index = ( shader_type == BindSymbol::SHADER_TYPE_GEOMETRY ) ? GetGeoShaderIndex() : GetVtxShaderIndex(); 847 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 848 849 // プログラム情報 850 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 851 852 // 出力属性情報 853 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 854 const BindSymbolInfo* bind_symbol_info = 855 reinterpret_cast< const BindSymbolInfo* >( 856 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 857 858 int num = 0; 859 860 // 検索 861 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 862 { 863 int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff; 864 865 if ( 120 <= regStart && regStart < 136 && 866 symbol_type == BindSymbol::SYMBOL_TYPE_BOOL ) 867 { 868 ++num; 869 } 870 else if ( 112 <= regStart && regStart < 115 && 871 symbol_type == BindSymbol::SYMBOL_TYPE_INTEGER ) 872 { 873 ++num; 874 } 875 else if ( 16 <= regStart && regStart < 111 && 876 symbol_type == BindSymbol::SYMBOL_TYPE_FLOAT ) 877 { 878 ++num; 879 } 880 else if ( regStart < 15 && 881 symbol_type == BindSymbol::SYMBOL_TYPE_INPUT ) 882 { 883 ++num; 884 } 885 } 886 887 return num; 888 } 889 890 //------------------------------------------------------------------------ 891 SearchBindSymbol(BindSymbol * symbol,const u8 symbol_index) const892 bool Shader::SearchBindSymbol( 893 BindSymbol* symbol, 894 const u8 symbol_index ) const 895 { 896 const BindSymbol::ShaderType shaderType = symbol->shaderType; 897 898 const int shader_index = ( shaderType == BindSymbol::SHADER_TYPE_GEOMETRY ) 899 ? GetGeoShaderIndex() : GetVtxShaderIndex(); 900 901 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 902 903 // プログラム情報 904 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 905 906 // シンボル情報 907 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 908 const BindSymbolInfo* bind_symbol_info = 909 reinterpret_cast< const BindSymbolInfo* >( 910 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 911 912 // 文字列情報 913 const char* string = 914 reinterpret_cast< const char* >( 915 reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset ); 916 917 int index = -1; 918 919 // 検索 920 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 921 { 922 int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff; 923 924 // Bool registers 925 if ( 120 <= regStart && regStart < 136 ) 926 { 927 ++index; 928 } 929 // Integer registers 930 else if ( 112 <= regStart && regStart < 115 ) 931 { 932 ++index; 933 } 934 // Constant registers 935 else if ( 16 <= regStart && regStart < 111 ) 936 { 937 ++index; 938 } 939 // Input registers 940 else if ( regStart < 15 ) 941 { 942 ++index; 943 } 944 else 945 { 946 return false; 947 } 948 949 if ( index == symbol_index ) 950 { 951 const BindSymbolInfo& info = bind_symbol_info[ i ]; 952 953 symbol->name = &string[ info.nameIndex ]; 954 symbol->start = (info.regIndex & 0x0000ffff); 955 symbol->end = (info.regIndex & 0xffff0000) >> 16; 956 957 if ( 120 <= symbol->start ) 958 { 959 symbol->start -= 120; 960 symbol->end -= 120; 961 962 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL; 963 } 964 else if ( 112 <= symbol->start ) 965 { 966 symbol->start -= 112; 967 symbol->end -= 112; 968 969 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER; 970 } 971 else if ( 16 <= symbol->start ) 972 { 973 symbol->start -= 16; 974 symbol->end -= 16; 975 976 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT; 977 } 978 else 979 { 980 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT; 981 } 982 } 983 } 984 985 return false; 986 } 987 988 } //namespace CTR 989 } //namespace gr 990 } //namespace nn 991