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