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: 26006 $ 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 u32* binary = reinterpret_cast< const u32* >( 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 u32* package_info = binary; 50 NN_GR_ASSERT( *binary == 0x504C5644 ); // DVLP 51 ++binary; 52 ++binary; 53 54 m_Instruction = reinterpret_cast< const u32* >( (u8*)package_info + *binary ); 55 ++binary; 56 57 m_InstructionCount = *binary; 58 ++binary; 59 60 const u32* swizzle = reinterpret_cast< const u32* >( (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(u32 * command) const104 u32* Shader::MakeFullCommand( u32* 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(u32 * command) const134 u32* Shader::MakePrepareCommand( u32* 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(u32 * command) const176 u32* Shader::MakeVtxProgramCommand( u32* command ) const 177 { 178 int shader_index = GetVtxShaderIndex(); 179 u32 reg_addr = PICA_REG_VS_PROG_ADDR; // 0x2cb 180 u32 reg_load = PICA_REG_VS_PROG_DATA0; // 0x2cc 181 u32 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(u32 * command) const216 u32* Shader::MakeGeoProgramCommand( u32* command ) const 217 { 218 int shader_index = GetGeoShaderIndex(); 219 u32 reg_addr = PICA_REG_GS_PROG_ADDR; // 0x29b 220 u32 reg_load = PICA_REG_GS_PROG_DATA0; // 0x29c 221 u32 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_(u32 * command,const bool is_geometry_shader)250 u32* Shader::MakeConstRgCommand_( u32* command, 251 const bool is_geometry_shader ) 252 { 253 int shader_index = GetVtxShaderIndex(); 254 u32 reg_float = PICA_REG_VS_FLOAT_ADDR; // 0x2c0 255 u32 reg_integer = PICA_REG_VS_INT0; // 0x2b1 256 u32* 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; u32 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 u32* 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_(u32 * command)310 u32* Shader::MakeOutAttrCommand_( u32* 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 u32 useTex = 0; 331 u32 clock = 0; 332 u32 outMask = 0; 333 u32 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 u32 gs_copy_mask = 0; 349 u32 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 u32 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 u32 vtxOutMask = 0; 459 u32 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 u32 gsDataMode = m_ExeImageInfo[ m_GeoShaderIndex ]->gsDataMode; 501 502 // GL_GEOMETRY_PRIMITIVE_DMP 503 *command++ = 0x00000000; 504 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa ); // 0x229 505 506 // GL_GEOMETRY_PRIMITIVE_DMP 507 *command++ = 0x00000000; 508 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 ); // 0x253 509 510 // 頂点シェーダーの出力数 511 *command++ = 0x08000000 | (gsDataMode == 0 ? 0x0000 : 0x0100) | vtxOutNum - 1; 512 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb ); // 0x289 513 514 // ジオメトリシェーダーのmainラベルのアドレス 515 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_GeoShaderIndex ]->mainAddress; 516 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_START_ADDR ); // 0x28a 517 518 // 頂点シェーダーの出力mask 519 *command++ = outMask; 520 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_OUT_REG_MASK ); // 0x28d 521 522 // 頂点シェーダーのmainラベルのアドレス 523 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress; 524 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR ); // 0x2ba 525 526 // 頂点シェーダーの出力レジスタマスク 527 *command++ = vtxOutMask; 528 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK ); // 0x2bd 529 530 // 頂点シェーダーの出力数 531 *command++ = vtxOutNum - 1; 532 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 ); // 0x251 533 534 // 頂点シェーダーの出力とジオメトリシェーダーの入力は一致させているのが前提 535 *command++ = 0x76543210; 536 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP0 ); // 0x28b 537 *command++ = 0xfedcba98; 538 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP1 ); // 0x28c 539 540 if ( gsDataMode == 2 ) 541 { 542 gsDataMode |= 0x01 << 24; 543 gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexStartIndex ) << 16; 544 gsDataMode |= ( vtxOutNum - 1 ) << 12; 545 gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1 ) << 8; 546 } 547 *command++ = gsDataMode; 548 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 ); // 0x252 549 550 *command++ = vtxOutNum - 1; 551 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 ); // 0x24a 552 } 553 else 554 { 555 *command++ = 0x00000100; 556 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa ); // 0x229 557 558 *command++ = 0x00000100; 559 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 ); // 0x253 560 561 // 頂点シェーダーのmainラベルのアドレス 562 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress; 563 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR ); // 0x2ba 564 565 // 頂点シェーダーの出力レジスタマスク 566 *command++ = outMask; 567 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK ); // 0x2bd 568 569 *command++ = outNum - 1; 570 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 ); // 0x251 571 572 *command++ = 0; 573 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 ); // 0x252 574 575 *command++ = outNum - 1; 576 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 ); // 0x24a 577 } 578 579 { 580 *command++ = outNum - 1; 581 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 1 ); // 0x25e 582 583 *command++ = outNum; 584 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM0 ); // 0x04f 585 586 // 出力属性のコマンド 587 outNum = 0; 588 for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index ) 589 { 590 if ( attr[ index ] != 0x1f1f1f1f ) 591 { 592 *command++ = attr[ index ]; 593 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + outNum ); 594 ++outNum; 595 } 596 } 597 for ( int index = outNum; index < OUT_ATTR_INDEX_MAX; ++index ) 598 { 599 *command++ = attr[ index ]; 600 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + index ); 601 } 602 } 603 604 // テクスチャ座標を使うかどうかを設定 605 *command++ = useTex; 606 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_MODE ); // 0x064 607 608 // 出力属性のクロック制御を設定 609 *command++ = clock; 610 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_CLK ); // 0x06f 611 612 if ( IsEnableGeoShader() ) 613 { 614 *command++ = 0; 615 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 8 ); // 0x25e 616 } 617 618 return command; 619 } 620 621 //------------------------------------------------------------------------ 622 MakeLoadCommand_(u32 * command,const u32 load_reg,const u32 * src_buffer_ptr,const u32 src_data_num) const623 u32* Shader::MakeLoadCommand_( u32* command, 624 const u32 load_reg, 625 const u32* src_buffer_ptr, 626 const u32 src_data_num ) const 627 { 628 enum { WRITE_MAX = 128 }; 629 630 u32 rest = src_data_num; 631 632 while ( true ) 633 { 634 if ( rest <= WRITE_MAX ) 635 { 636 *command++ = *src_buffer_ptr++; 637 *command++ = PICA_CMD_HEADER_BURST( load_reg, rest ); 638 std::memcpy( command, src_buffer_ptr, ( rest - 1 ) * sizeof( u32 ) ); 639 command += rest - 1; 640 641 if ( ( rest & 1 ) == 0 ) *command++ = PADDING_DATA; // padding 642 break; 643 } 644 else 645 { 646 *command++ = *src_buffer_ptr++; 647 *command++ = PICA_CMD_HEADER_BURST( load_reg, WRITE_MAX ); 648 std::memcpy( command, src_buffer_ptr, ( WRITE_MAX - 1 ) * sizeof( u32 ) ); 649 650 command += WRITE_MAX - 1; 651 src_buffer_ptr += WRITE_MAX - 1; 652 653 rest -= WRITE_MAX; 654 if ( ( WRITE_MAX & 1 ) == 0 ) *command++ = PADDING_DATA; // padding 655 } 656 } 657 658 return command; 659 } 660 661 //------------------------------------------------------------------------ 662 MakeDummyCommand_(u32 * command,const u32 load_reg,const u32 dataNum) const663 u32* Shader::MakeDummyCommand_( u32* command, 664 const u32 load_reg, 665 const u32 dataNum ) const 666 { 667 *command++ = 0; 668 *command++ = PICA_CMD_HEADER_BURST_BE( load_reg, dataNum, 0 ); 669 670 for ( int i = 0; i < dataNum - ( dataNum & 1 ); ++i) 671 { 672 *command++ = PADDING_DATA; 673 } 674 675 return command; 676 } 677 678 //------------------------------------------------------------------------ 679 SearchBindSymbol(BindSymbol * symbol,const char * name) const680 bool Shader::SearchBindSymbol( BindSymbol* symbol, 681 const char* name ) const 682 { 683 const int shader_index = symbol->shaderType == BindSymbol::SHADER_TYPE_GEOMETRY ? GetGeoShaderIndex() : GetVtxShaderIndex(); 684 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 685 686 // プログラム情報 687 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 688 689 // シンボル情報 690 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 691 const BindSymbolInfo* bind_symbol_info = 692 reinterpret_cast< const BindSymbolInfo* >( 693 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 694 695 // 文字列情報 696 const char* string = 697 reinterpret_cast< const char* >( 698 reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset ); 699 700 // 検索 701 u32 namelen = std::strlen( name ); 702 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 703 { 704 const BindSymbolInfo& info = bind_symbol_info[ i ]; 705 706 if ( std::strncmp( name, &string[ info.nameIndex ], namelen ) != 0 ) continue; 707 if ( string[ info.nameIndex + namelen ] != '\0' && string[ info.nameIndex + namelen ] != '.' ) continue; 708 709 symbol->name = &string[ info.nameIndex ]; 710 symbol->start = (info.regIndex & 0x0000ffff); 711 symbol->end = (info.regIndex & 0xffff0000) >> 16; 712 713 if ( 136 <= symbol->start ) 714 { 715 return false; 716 } 717 else if ( 120 <= symbol->start ) 718 { 719 symbol->start -= 120; 720 symbol->end -= 120; 721 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL; 722 } 723 else if ( 112 <= symbol->start ) 724 { 725 symbol->start -= 112; 726 symbol->end -= 112; 727 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER; 728 } 729 else if ( 16 <= symbol->start ) 730 { 731 symbol->start -= 16; 732 symbol->end -= 16; 733 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT; 734 } 735 else 736 { 737 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT; 738 } 739 } 740 741 return false; 742 } 743 744 //------------------------------------------------------------------------ 745 SearchBindSymbolNum(const BindSymbol::ShaderType shader_type,const BindSymbol::SymbolType symbol_type) const746 u32 Shader::SearchBindSymbolNum( 747 const BindSymbol::ShaderType shader_type, 748 const BindSymbol::SymbolType symbol_type ) const 749 { 750 const int shader_index = ( shader_type == BindSymbol::SHADER_TYPE_GEOMETRY ) ? GetGeoShaderIndex() : GetVtxShaderIndex(); 751 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 752 753 // プログラム情報 754 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 755 756 // 出力属性情報 757 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 758 const BindSymbolInfo* bind_symbol_info = 759 reinterpret_cast< const BindSymbolInfo* >( 760 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 761 762 int num = 0; 763 764 // 検索 765 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 766 { 767 int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff; 768 769 if ( 120 <= regStart && regStart < 136 && symbol_type == BindSymbol::SYMBOL_TYPE_BOOL ) ++num; 770 else if ( 112 <= regStart && regStart < 115 && symbol_type == BindSymbol::SYMBOL_TYPE_INTEGER ) ++num; 771 else if ( 16 <= regStart && regStart < 111 && symbol_type == BindSymbol::SYMBOL_TYPE_FLOAT ) ++num; 772 else if ( regStart < 15 && symbol_type == BindSymbol::SYMBOL_TYPE_INPUT ) ++num; 773 } 774 775 return num; 776 } 777 778 //------------------------------------------------------------------------ 779 SearchBindSymbol(BindSymbol * symbol,const u8 symbol_index) const780 bool Shader::SearchBindSymbol( 781 BindSymbol* symbol, 782 const u8 symbol_index ) const 783 { 784 const BindSymbol::SymbolType type = symbol->symbolType; 785 786 const int shader_index = type == ( BindSymbol::SHADER_TYPE_GEOMETRY ) ? GetGeoShaderIndex() : GetVtxShaderIndex(); 787 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 788 789 // プログラム情報 790 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 791 792 // シンボル情報 793 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 794 const BindSymbolInfo* bind_symbol_info = 795 reinterpret_cast< const BindSymbolInfo* >( 796 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 797 798 // 文字列情報 799 const char* string = 800 reinterpret_cast< const char* >( 801 reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset ); 802 803 int index = -1; 804 805 // 検索 806 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 807 { 808 int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff; 809 810 if ( 120 <= regStart && regStart < 136 && type == BindSymbol::SYMBOL_TYPE_BOOL ) ++index; 811 else if ( 112 <= regStart && regStart < 115 && type == BindSymbol::SYMBOL_TYPE_INTEGER ) ++index; 812 else if ( 16 <= regStart && regStart < 111 && type == BindSymbol::SYMBOL_TYPE_FLOAT ) ++index; 813 else if ( regStart < 15 && type == BindSymbol::SYMBOL_TYPE_INPUT ) ++index; 814 815 if ( index == symbol_index ) 816 { 817 const BindSymbolInfo& info = bind_symbol_info[ i ]; 818 symbol->name = &string[ info.nameIndex ]; 819 symbol->start = (info.regIndex & 0x0000ffff); 820 symbol->end = (info.regIndex & 0xffff0000) >> 16; 821 822 if ( 120 <= symbol->start ) { symbol->start -= 120; symbol->end -= 120; } 823 else if ( 112 <= symbol->start ) { symbol->start -= 112; symbol->end -= 112; } 824 else if ( 16 <= symbol->start ) { symbol->start -= 16; symbol->end -= 16; } 825 return true; 826 } 827 } 828 829 return false; 830 } 831 832 } //namespace CTR 833 } //namespace gr 834 } //namespace nn 835