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: 35551 $ 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 417 // 最初にVSとGS両方で指定されているものを設定. 418 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX ); 419 for( s32 g = 0; g < exe_info->outMapCount; ++g ) 420 { 421 // GS の generic 属性( 値 9 ) は除きます 422 if ( ( outmapInfo[ g ].type >= 0 ) && 423 ( outmapInfo[ g ].type < 9 ) && 424 ( outmapInfo[ g ].type != 7 ) ) 425 { 426 for( s32 v = 0; v < vtx_exe_info->outMapCount; ++v ) 427 { 428 // VS の generic 属性( 値 9 ) は除きます 429 if ( ( vtxOutmapInfo[ v ].type >= 0 ) && 430 ( vtxOutmapInfo[ v ].type < 9 ) && 431 ( vtxOutmapInfo[ v ].type != 7 ) ) 432 { 433 if ( outmapInfo[ g ].type == vtxOutmapInfo[ v ].type ) 434 { 435 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_INDEX_MAX ); 436 outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type; 437 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount; 438 outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask; 439 gs_copy_mask |= 1 << g; 440 vs_copy_mask |= 1 << v; 441 ++outMapBufferCount; 442 } 443 } 444 } 445 } 446 } 447 448 // 次にGSのみで定義されているものを設定. 449 for( s32 g = 0; g < exe_info->outMapCount; ++g ) 450 { 451 if ( ( !( gs_copy_mask & ( 1 << g ) ) ) && 452 ( outmapInfo[ g ].type >= 0 ) && 453 ( outmapInfo[ g ].type < 9 ) && 454 ( outmapInfo[ g ].type != 7 ) ) 455 { 456 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX ); 457 outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type; 458 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount; 459 outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask; 460 ++outMapBufferCount; 461 } 462 } 463 464 // 最後ににVSのみで定義されているものを設定. 465 for( s32 v = 0; v < vtx_exe_info->outMapCount; ++v ) 466 { 467 if ( ( !( vs_copy_mask & ( 1 << v ) ) ) && 468 ( vtxOutmapInfo[ v ].type >= 0 ) && 469 ( vtxOutmapInfo[ v ].type < 9 ) && 470 ( vtxOutmapInfo[ v ].type != 7 ) ) 471 { 472 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX ); 473 outmap_buffer[ outMapBufferCount ].type = vtxOutmapInfo[ v ].type; 474 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount; 475 outmap_buffer[ outMapBufferCount ].mask = vtxOutmapInfo[ v ].mask; 476 ++outMapBufferCount; 477 } 478 } 479 } 480 else 481 { 482 // 出力属性情報 483 const OutmapInfo* outmapInfo = 484 reinterpret_cast< const OutmapInfo* >( 485 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset ); 486 // マージしない場合はコピー. 487 for( int i = 0; i < exe_info->outMapCount; ++i ) 488 { 489 outmap_buffer[ i ] = outmapInfo[ i ]; 490 } 491 outMapBufferCount = exe_info->outMapCount; 492 } 493 494 for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index ) 495 { 496 attr[ index ] = 0x1f1f1f1f; 497 for ( int i = 0; i <outMapBufferCount; ++i ) 498 { 499 bit32 c = 0; 500 for ( int j = 0; outmap_buffer[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j ) 501 { 502 if ( ( outmap_buffer[ i ].mask & ( 1 << j ) ) == 0 ) continue; 503 504 int value = 0x1f; 505 switch ( outmap_buffer[ i ].type ) 506 { 507 case 0 : value = 0x00 + c++; if (c == 2) clock |= 1 << 0; break; // position 508 case 1 : value = 0x04 + c++; clock |= 1 << 24; break; // quaternion 509 case 2 : value = 0x08 + c++; clock |= 1 << 1; break; // color 510 case 3 : if (c < 2) value = 0x0c + c++; useTex = 1; clock |= 1 << 8; break; // texcoord0 511 case 4 : value = 0x10; useTex = 1; clock |= 3 << 16; break; // texcoord0w 512 case 5 : if (c < 2) value = 0x0e + c++; useTex = 1; clock |= 1 << 9; break; // texcoord1 513 case 6 : if (c < 2) value = 0x16 + c++; useTex = 1; clock |= 1 << 10; break; // texcoord2 514 case 8 : if (c < 3) value = 0x12 + c++; clock |= 1 << 24; break; // view 515 } 516 attr[ index ] = attr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 ); 517 } 518 } 519 if ( attr[ index ] != 0x1f1f1f1f ) 520 { 521 outMask |= ( 1 << index ); 522 ++outNum; 523 } 524 } 525 } 526 527 if ( IsEnableGeoShader() ) 528 { 529 // 頂点シェーダーの出力属性の設定をもとめる 530 m_DrawMode = PICA_DATA_DRAW_GEOMETRY_PRIMITIVE; 531 532 u32 vtxOutNum = 0; 533 bit32 vtxOutMask = 0; 534 bit32 vtxAttr[ VS_OUT_ATTR_INDEX_MAX ]; 535 536 // プログラム情報 537 const ExeImageInfo* exe_info = m_ExeImageInfo[ m_VtxShaderIndex ]; 538 const OutmapInfo* outmapInfo = 539 reinterpret_cast< const OutmapInfo* >( 540 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset ); 541 542 for ( int index = 0; index < VS_OUT_ATTR_INDEX_MAX; ++index ) 543 { 544 vtxAttr[ index ] = 0x1f1f1f1f; 545 for ( int i = 0; i < exe_info->outMapCount; ++i ) 546 { 547 u32 c = 0; 548 for ( int j = 0; outmapInfo[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j ) 549 { 550 if ( ( outmapInfo[ i ].mask & ( 1 << j ) ) == 0 ) continue; 551 552 int value = 0x1f; 553 switch ( outmapInfo[ i ].type ) 554 { 555 case 0 : value = 0x00 + c++; break; // position 556 case 1 : value = 0x04 + c++; break; // quaternion 557 case 2 : value = 0x08 + c++; break; // color 558 case 3 : if (c < 2) value = 0x0c + c++; break; // texcoord0 559 case 4 : value = 0x10; break; // texcoord0w 560 case 5 : if (c < 2) value = 0x0e + c++; break; // texcoord1 561 case 6 : if (c < 2) value = 0x16 + c++; break; // texcoord2 562 case 8 : if (c < 3) value = 0x12 + c++; break; // view 563 case 9 : value = 0xff; 564 } 565 vtxAttr[ index ] = vtxAttr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 ); 566 } 567 } 568 if ( vtxAttr[ index ] != 0x1f1f1f1f ) 569 { 570 vtxOutMask |= ( 1 << index ); 571 ++vtxOutNum; 572 } 573 } 574 575 bit32 gsDataMode = m_ExeImageInfo[ m_GeoShaderIndex ]->gsDataMode; 576 577 // GL_GEOMETRY_PRIMITIVE_DMP 578 579 // 0x229 [31:31], 580 // データモード 1 の場合 581 if ( gsDataMode == 1 ) 582 { 583 *command++ = 0x80000000; 584 } 585 // データモード 0 と データモード2 の場合 586 else 587 { 588 *command++ = 0x00000000; 589 } 590 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa ); 591 592 // 0x253 593 *command++ = 0x00000000; 594 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 ); 595 596 // 0x289 頂点シェーダーの出力数 597 *command++ = 0x08000000 | (gsDataMode == 0 ? 0x0000 : 0x0100) | vtxOutNum - 1; 598 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb ); 599 600 // 0x28a ジオメトリシェーダーのmainラベルのアドレス 601 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_GeoShaderIndex ]->mainAddress; 602 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_START_ADDR ); 603 604 // 0x28d 頂点シェーダーの出力mask 605 *command++ = outMask; 606 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_OUT_REG_MASK ); 607 608 // 0x2ba 頂点シェーダーのmainラベルのアドレス 609 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress; 610 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR ); 611 612 // 0x2bd 頂点シェーダーの出力レジスタマスク 613 *command++ = vtxOutMask; 614 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK ); 615 616 // 0x251 頂点シェーダーの出力数 617 *command++ = vtxOutNum - 1; 618 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 ); 619 620 // 0x28b 頂点シェーダーの出力とジオメトリシェーダーの入力は一致させているのが前提 621 *command++ = 0x76543210; 622 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP0 ); // 0x28b 623 624 // 0x28c 625 *command++ = 0xfedcba98; 626 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP1 ); 627 628 // 0x254 629 if ( ( gsDataMode == 1 ) && ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum != 0 ) ) 630 { 631 *command++ = m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1; 632 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_MISC_REG1, 0x1 ); 633 } 634 635 // 0x252 用の値 636 if ( gsDataMode == 2 ) 637 { 638 gsDataMode |= 0x01 << 24; 639 gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexStartIndex ) << 16; 640 gsDataMode |= ( vtxOutNum - 1 ) << 12; 641 gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1 ) << 8; 642 } 643 644 // 0x252 データモードの指定 645 *command++ = gsDataMode; 646 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 ); 647 648 // 0x24a 649 *command++ = vtxOutNum - 1; 650 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 ); 651 } 652 else 653 { 654 // 0x229 [31:31] 655 *command++ = 0x0; 656 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0x8 ); 657 658 // 0x253 [0:0] 659 *command++ = 0x0; 660 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x1 ); 661 662 // 0x289 [31:24], [15:8], [3:0] 頂点シェーダーのモードの設定 663 *command++ = 0xa0000000; 664 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb ); 665 666 // 0x2ba 頂点シェーダーのmainラベルのアドレス 667 *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress; 668 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR ); 669 670 // 0x2bd 頂点シェーダーの出力レジスタマスク 671 *command++ = outMask; 672 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK ); 673 674 // 0x251 675 *command++ = outNum - 1; 676 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 ); 677 678 // 0x252 679 *command++ = 0; 680 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 ); 681 682 // 0x24a 683 *command++ = outNum - 1; 684 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 ); 685 } 686 687 { 688 // 0x25e [3:0] 689 *command++ = outNum - 1; 690 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 0x1 ); 691 692 // 0x04f 693 *command++ = outNum; 694 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM0 ); 695 696 // 出力属性のコマンド 697 outNum = 0; 698 for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index ) 699 { 700 if ( attr[ index ] != 0x1f1f1f1f ) 701 { 702 *command++ = attr[ index ]; 703 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + outNum ); 704 ++outNum; 705 } 706 } 707 for ( int index = outNum; index < OUT_ATTR_INDEX_MAX; ++index ) 708 { 709 *command++ = attr[ index ]; 710 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + index ); 711 } 712 } 713 714 // 0x064 テクスチャ座標を使うかどうかを設定 715 *command++ = useTex; 716 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_MODE ); 717 718 // 0x06f 出力属性のクロック制御を設定 719 *command++ = clock; 720 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_CLK ); 721 722 if ( IsEnableGeoShader() ) 723 { 724 // 0x25e 725 *command++ = 0; 726 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 8 ); 727 } 728 729 return command; 730 } 731 732 //------------------------------------------------------------------------ 733 MakeLoadCommand_(bit32 * command,const bit32 load_reg,const bit32 * src_buffer_ptr,const u32 src_data_num) const734 bit32* Shader::MakeLoadCommand_( bit32* command, 735 const bit32 load_reg, 736 const bit32* src_buffer_ptr, 737 const u32 src_data_num ) const 738 { 739 enum { WRITE_MAX = 128 }; 740 741 u32 rest = src_data_num; 742 743 while ( true ) 744 { 745 if ( rest <= WRITE_MAX ) 746 { 747 *command++ = *src_buffer_ptr++; 748 *command++ = PICA_CMD_HEADER_BURST( load_reg, rest ); 749 std::memcpy( command, src_buffer_ptr, ( rest - 1 ) * sizeof( bit32 ) ); 750 command += rest - 1; 751 752 if ( ( rest & 1 ) == 0 ) *command++ = PADDING_DATA; // padding 753 break; 754 } 755 else 756 { 757 *command++ = *src_buffer_ptr++; 758 *command++ = PICA_CMD_HEADER_BURST( load_reg, WRITE_MAX ); 759 std::memcpy( command, src_buffer_ptr, ( WRITE_MAX - 1 ) * sizeof( bit32 ) ); 760 761 command += WRITE_MAX - 1; 762 src_buffer_ptr += WRITE_MAX - 1; 763 764 rest -= WRITE_MAX; 765 if ( ( WRITE_MAX & 1 ) == 0 ) *command++ = PADDING_DATA; // padding 766 } 767 } 768 769 return command; 770 } 771 772 //------------------------------------------------------------------------ 773 MakeDummyCommand_(bit32 * command,const bit32 load_reg,const u32 dataNum)774 bit32* Shader::MakeDummyCommand_( bit32* command, 775 const bit32 load_reg, 776 const u32 dataNum ) 777 { 778 *command++ = 0; 779 *command++ = PICA_CMD_HEADER_BURST_BE( load_reg, dataNum, 0 ); 780 781 for ( int i = 0; i < dataNum - ( dataNum & 1 ); ++i) 782 { 783 *command++ = PADDING_DATA; 784 } 785 786 return command; 787 } 788 789 //------------------------------------------------------------------------ 790 SearchBindSymbol(BindSymbol * symbol,const char * name) const791 bool Shader::SearchBindSymbol( BindSymbol* symbol, 792 const char* name ) const 793 { 794 const int shader_index = ( symbol->shaderType == BindSymbol::SHADER_TYPE_GEOMETRY ) 795 ? GetGeoShaderIndex() : GetVtxShaderIndex(); 796 797 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 798 799 // プログラム情報 800 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 801 802 // シンボル情報 803 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 804 const BindSymbolInfo* bind_symbol_info = 805 reinterpret_cast< const BindSymbolInfo* >( 806 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 807 808 // 文字列情報 809 const char* string = 810 reinterpret_cast< const char* >( 811 reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset ); 812 813 // 検索 814 u32 namelen = std::strlen( name ); 815 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 816 { 817 const BindSymbolInfo& info = bind_symbol_info[ i ]; 818 819 if ( std::strncmp( name, &string[ info.nameIndex ], namelen ) != 0 ) continue; 820 if ( string[ info.nameIndex + namelen ] != '\0' && string[ info.nameIndex + namelen ] != '.' ) continue; 821 822 symbol->name = &string[ info.nameIndex ]; 823 symbol->start = (info.regIndex & 0x0000ffff); 824 symbol->end = (info.regIndex & 0xffff0000) >> 16; 825 826 if ( 136 <= symbol->start ) 827 { 828 return false; 829 } 830 else if ( 120 <= symbol->start ) 831 { 832 symbol->start -= 120; 833 symbol->end -= 120; 834 835 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL; 836 } 837 else if ( 112 <= symbol->start ) 838 { 839 symbol->start -= 112; 840 symbol->end -= 112; 841 842 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER; 843 } 844 else if ( 16 <= symbol->start ) 845 { 846 symbol->start -= 16; 847 symbol->end -= 16; 848 849 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT; 850 } 851 else 852 { 853 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT; 854 } 855 } 856 857 return false; 858 } 859 860 //------------------------------------------------------------------------ 861 SearchBindSymbolNum(const BindSymbol::ShaderType shader_type,const BindSymbol::SymbolType symbol_type) const862 u32 Shader::SearchBindSymbolNum( 863 const BindSymbol::ShaderType shader_type, 864 const BindSymbol::SymbolType symbol_type ) const 865 { 866 const int shader_index = ( shader_type == BindSymbol::SHADER_TYPE_GEOMETRY ) ? GetGeoShaderIndex() : GetVtxShaderIndex(); 867 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 868 869 // プログラム情報 870 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 871 872 // 出力属性情報 873 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 874 const BindSymbolInfo* bind_symbol_info = 875 reinterpret_cast< const BindSymbolInfo* >( 876 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 877 878 int num = 0; 879 880 // 検索 881 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 882 { 883 int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff; 884 885 if ( 120 <= regStart && regStart < 136 && 886 symbol_type == BindSymbol::SYMBOL_TYPE_BOOL ) 887 { 888 ++num; 889 } 890 else if ( 112 <= regStart && regStart < 115 && 891 symbol_type == BindSymbol::SYMBOL_TYPE_INTEGER ) 892 { 893 ++num; 894 } 895 else if ( 16 <= regStart && regStart < 111 && 896 symbol_type == BindSymbol::SYMBOL_TYPE_FLOAT ) 897 { 898 ++num; 899 } 900 else if ( regStart < 15 && 901 symbol_type == BindSymbol::SYMBOL_TYPE_INPUT ) 902 { 903 ++num; 904 } 905 } 906 907 return num; 908 } 909 910 //------------------------------------------------------------------------ 911 SearchBindSymbol(BindSymbol * symbol,const u8 symbol_index) const912 bool Shader::SearchBindSymbol( 913 BindSymbol* symbol, 914 const u8 symbol_index ) const 915 { 916 const BindSymbol::ShaderType shaderType = symbol->shaderType; 917 918 const int shader_index = ( shaderType == BindSymbol::SHADER_TYPE_GEOMETRY ) 919 ? GetGeoShaderIndex() : GetVtxShaderIndex(); 920 921 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum ); 922 923 // プログラム情報 924 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ]; 925 926 // シンボル情報 927 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; }; 928 const BindSymbolInfo* bind_symbol_info = 929 reinterpret_cast< const BindSymbolInfo* >( 930 reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset ); 931 932 // 文字列情報 933 const char* string = 934 reinterpret_cast< const char* >( 935 reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset ); 936 937 int index = -1; 938 939 // 検索 940 for ( int i = 0; i < exe_info->bindSymbolCount; ++i ) 941 { 942 int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff; 943 944 // Bool registers 945 if ( 120 <= regStart && regStart < 136 ) 946 { 947 ++index; 948 } 949 // Integer registers 950 else if ( 112 <= regStart && regStart < 115 ) 951 { 952 ++index; 953 } 954 // Constant registers 955 else if ( 16 <= regStart && regStart < 111 ) 956 { 957 ++index; 958 } 959 // Input registers 960 else if ( regStart < 15 ) 961 { 962 ++index; 963 } 964 else 965 { 966 return false; 967 } 968 969 if ( index == symbol_index ) 970 { 971 const BindSymbolInfo& info = bind_symbol_info[ i ]; 972 973 symbol->name = &string[ info.nameIndex ]; 974 symbol->start = (info.regIndex & 0x0000ffff); 975 symbol->end = (info.regIndex & 0xffff0000) >> 16; 976 977 if ( 120 <= symbol->start ) 978 { 979 symbol->start -= 120; 980 symbol->end -= 120; 981 982 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL; 983 } 984 else if ( 112 <= symbol->start ) 985 { 986 symbol->start -= 112; 987 symbol->end -= 112; 988 989 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER; 990 } 991 else if ( 16 <= symbol->start ) 992 { 993 symbol->start -= 16; 994 symbol->end -= 16; 995 996 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT; 997 } 998 else 999 { 1000 return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT; 1001 } 1002 } 1003 } 1004 1005 return false; 1006 } 1007 1008 } //namespace CTR 1009 } //namespace gr 1010 } //namespace nn 1011