1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: gfx_ShaderBinaryInfo.h 4 5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. 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 $Revision: 28011 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NW_GFX_SHADERBINARYINFO_H_ 17 #define NW_GFX_SHADERBINARYINFO_H_ 18 19 #include <GLES2/gl2.h> 20 #include <GLES2/gl2ext.h> 21 22 #include <nw/types.h> 23 #include <nw/ut/ut_Inlines.h> 24 #include <nw/gfx/gfx_CommandUtil.h> 25 26 // シェーダバイナリの解析等のシェーダ用のドライバ層です。 27 28 namespace nw 29 { 30 namespace gfx 31 { 32 33 //--------------------------------------------------------------------------- 34 //! @brief シェーダバイナリを解析し、コマンドの生成等の処理をおこなうクラスです。 35 //--------------------------------------------------------------------------- 36 class ShaderBinaryInfo 37 { 38 private: 39 class SafeBuffer; 40 41 public: 42 // シンボルの型 43 enum SymbolType 44 { 45 SYMBOL_TYPE_INVALID, //!< 不正な型。 46 SYMBOL_TYPE_INPUT, //!< 頂点属性。(v0 ... v15) 47 SYMBOL_TYPE_FLOAT, //!< 浮動小数定数レジスタ。 (c0 ... c95) 48 SYMBOL_TYPE_INT, //!< 整数定数レジスタ。(i0 ... i3) 49 SYMBOL_TYPE_BOOL //!< ブール定数レジスタ。(b0 ... b15) 50 }; 51 52 //--------------------------------------------------------------------------- 53 //! @brief コンストラクタです。 54 //! 55 //! @param[in] shaderBinary シェーダバイナリへのポインタです。 56 //--------------------------------------------------------------------------- ShaderBinaryInfo(const void * shaderBinary)57 ShaderBinaryInfo( const void* shaderBinary ) 58 : m_pShaderBinary( reinterpret_cast<const u32*>(shaderBinary) ), 59 m_ExeImageCount( 0 ), 60 m_pInstruction( NULL ), 61 m_InstructionCount( 0 ), 62 m_SwizzleCount( 0 ), 63 m_GeometryShaderCount( 0 ) 64 { 65 for (int i = 0; i < EXE_IMAGE_MAX; ++i) 66 { 67 m_ExeImageInfo[ i ] = NULL; 68 } 69 70 // デバッグビルド以外では、m_Swizzle のクリア処理は行なわない。 71 #if defined(NW_DEBUG) 72 for (int i = 0; i < SWIZZLE_PATTERN_MAX; ++i) 73 { 74 m_Swizzle[ i ] = 0; 75 } 76 #endif 77 } 78 79 //--------------------------------------------------------------------------- 80 //! @brief シェーダバイナリ転送用コマンドのサイズを取得します。 81 //! 82 //! @return シェーダバイナリ転送用に必要なコマンドサイズです。 83 //--------------------------------------------------------------------------- 84 s32 GetCommonCommandSize() const; 85 86 //--------------------------------------------------------------------------- 87 //! @brief 指定したバッファにシェーダバイナリ転送用のコマンドを作成します。 88 //! 89 //! @param[out] bufferAddress コマンドを生成するバッファのアドレスです。 90 //! @param[in] bufferSize バッファの最大サイズです。 91 //! 92 //! @return 出力したコマンドサイズです。 93 //--------------------------------------------------------------------------- 94 s32 BuildCommonCommand( u32* bufferAddress, u32 bufferSize ) const; 95 96 //--------------------------------------------------------------------------- 97 //! @brief カレントのコマンドバッファにシェーダバイナリ転送用のコマンドを 98 //! 作成します。 99 //! 100 //! @return 出力したコマンドサイズです。 101 //--------------------------------------------------------------------------- BuildCommonCommand()102 s32 BuildCommonCommand() const 103 { 104 u32* currentBuffer = static_cast<u32*>( internal::NWGetCurrentCmdBuffer() ); 105 u32* cmdBufferEnd = static_cast<u32*>( internal::NWGetCmdBufferEnd() ); 106 u32 bufferSize = ut::GetOffsetFromPtr( currentBuffer, cmdBufferEnd ); 107 108 s32 result = this->BuildCommonCommand( currentBuffer, bufferSize ); 109 110 if ( result > 0 ) 111 { 112 internal::NWForwardCurrentCmdBuffer( result ); 113 } 114 115 return result; 116 } 117 118 //--------------------------------------------------------------------------- 119 //! @brief シェーダプログラム設定用コマンドのサイズを取得します。 120 //! 121 //! @param[in] vertexIndex 頂点シェーダのインデックスを指定します。 122 //! @param[in] geometryIndex ジオメトリシェーダのインデックスを指定します。 123 //! 124 //! @return シェーダプログラム設定用に必要なコマンドサイズです。 125 //--------------------------------------------------------------------------- 126 s32 GetShaderProgramCommandSize( s32 vertexIndex, s32 geometryIndex ) const; 127 128 //--------------------------------------------------------------------------- 129 //! @brief シェーダプログラム設定用のコマンドを作成します。 130 //! 131 //! @param[in] vertexIndex 頂点シェーダのインデックスを指定します。 132 //! @param[in] geometryIndex ジオメトリシェーダのインデックスを指定します。 133 //! @param[out] bufferAddress コマンドを生成するバッファのアドレスです。 134 //! @param[in] bufferSize バッファの最大サイズです。 135 //! 136 //! @return 出力したコマンドサイズです。 137 //--------------------------------------------------------------------------- 138 s32 BuildShaderProgramCommand( s32 vertexIndex, s32 geometryIndex, u32* bufferAddress, u32 bufferSize ) const; 139 140 //--------------------------------------------------------------------------- 141 //! @brief 指定したバッファにシェーダプログラム設定用のコマンドを作成します。 142 //! 143 //! @param[in] vertexIndex 頂点シェーダのインデックスです。 144 //! @param[in] geometryIndex ジオメトリシェーダのインデックスです。 145 //! 146 //! @return 出力したコマンドサイズです。 147 //--------------------------------------------------------------------------- BuildShaderProgramCommand(s32 vertexIndex,s32 geometryIndex)148 s32 BuildShaderProgramCommand( s32 vertexIndex, s32 geometryIndex ) const 149 { 150 u32* currentBuffer = static_cast<u32*>( internal::NWGetCurrentCmdBuffer() ); 151 u32* cmdBufferEnd = static_cast<u32*>( internal::NWGetCmdBufferEnd() ); 152 u32 bufferSize = ut::GetOffsetFromPtr( currentBuffer, cmdBufferEnd ); 153 154 s32 result = this->BuildShaderProgramCommand( vertexIndex, geometryIndex, currentBuffer, bufferSize ); 155 156 if ( result > 0 ) 157 { 158 internal::NWForwardCurrentCmdBuffer( result ); 159 } 160 161 return result; 162 } 163 164 //--------------------------------------------------------------------------- 165 //! @name シェーダプログラムの情報へのアクセサ 166 //@{ 167 168 //--------------------------------------------------------------------------- 169 //! @brief ジオメトリシェーダかどうかを取得します。 170 //! 171 //! @param[in] shaderIndex シェーダインデックスです。 172 //! 173 //! @return 指定したシェーダがジオメトリシェーダであれば true を返します。 174 //--------------------------------------------------------------------------- IsGeometryShader(s32 shaderIndex)175 bool IsGeometryShader(s32 shaderIndex) const 176 { 177 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 178 179 return exeInfo->isGeometryShader ? true : false; 180 } 181 182 //--------------------------------------------------------------------------- 183 //! @brief 頂点ユニフォームインデックスを取得します。 184 //! 185 //! @param[in] shaderIndex シェーダインデックスです。 186 //! @param[in] name 頂点ユニフォームの名前です。 187 //! 188 //! @return 対応する頂点インデックスと型情報の組み合わせを取得します。 189 //--------------------------------------------------------------------------- 190 // NOTE: コンパイラの不具合で、pair が正しく返せない場合があるので、noinline にしておく。 191 __declspec(noinline) ::std::pair<s32, SymbolType> SearchUniformIndex(s32 shaderIndex,const char * name)192 SearchUniformIndex(s32 shaderIndex, const char* name) const 193 { 194 enum { BEGIN_INPUT = 0, BEGIN_FLOAT = 16, BEGIN_INT = 112, BEGIN_BOOL = 120, END_SYMBOL = 136 }; 195 196 // 出力属性情報 197 struct BindSymbolInfo 198 { 199 u32 nameIndex; 200 u32 regIndex; 201 }; 202 203 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 204 205 const BindSymbolInfo* bindSymbolInfoTable = static_cast<const BindSymbolInfo*>( ut::AddOffsetToPtr(exeInfo, exeInfo->bindSymbolOffset) ); 206 const char* stringTable = static_cast<const char*>( ut::AddOffsetToPtr(exeInfo, exeInfo->stringOffset) ); 207 208 SymbolType symbolType = SYMBOL_TYPE_INVALID; 209 s32 symbolIndex = -1; 210 211 u32 nameLen = std::strlen( name ); 212 for (int i = 0; i < static_cast<int>(exeInfo->bindSymbolCount); ++i) 213 { 214 const BindSymbolInfo& info = bindSymbolInfoTable[ i ]; 215 216 const char* symbolName = &stringTable[ info.nameIndex ]; 217 218 if ( std::strncmp( name, symbolName, nameLen ) != 0 ) { continue; } 219 if ( symbolName[ nameLen ] != '\0' && symbolName[ nameLen ] != '.' ) { continue; } 220 221 symbolIndex = static_cast<s32>( info.regIndex & 0x0000ffff ); 222 223 if ( END_SYMBOL <= symbolIndex ) { symbolIndex = -1; } 224 else if (BEGIN_BOOL <= symbolIndex ) { symbolType = SYMBOL_TYPE_BOOL; symbolIndex = symbolIndex - BEGIN_BOOL; } 225 else if (BEGIN_INT <= symbolIndex ) { symbolType = SYMBOL_TYPE_INT; symbolIndex = symbolIndex - BEGIN_INT; } 226 else if (BEGIN_FLOAT <= symbolIndex ) { symbolType = SYMBOL_TYPE_FLOAT; symbolIndex = symbolIndex - BEGIN_FLOAT; } 227 else { symbolType = SYMBOL_TYPE_INPUT; symbolIndex = symbolIndex; } 228 229 break; 230 } 231 232 return std::make_pair(symbolIndex, symbolType); 233 } 234 235 //--------------------------------------------------------------------------- 236 //! @brief 頂点ユニフォームインデックスを取得します。 237 //! 238 //! @param[in] shaderIndex シェーダインデックスです。 239 //! @param[in] symbolType レジスタの種類です。 240 //! @param[in] index レジスタのインデックスです。 241 //! 242 //! @return 対応する頂点インデックスとジオメトリシェーダフラグの組み合わせを取得します。 243 //--------------------------------------------------------------------------- 244 const char* SearchUniformIndex(s32 shaderIndex,SymbolType symbolType,s32 index)245 SearchUniformIndex(s32 shaderIndex, SymbolType symbolType, s32 index) const 246 { 247 enum { BEGIN_INPUT = 0, BEGIN_FLOAT = 16, BEGIN_INT = 112, BEGIN_BOOL = 120, END_SYMBOL = 136 }; 248 249 // 出力属性情報 250 struct BindSymbolInfo 251 { 252 u32 nameIndex; 253 u32 regIndex; 254 }; 255 256 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 257 258 const BindSymbolInfo* bindSymbolInfoTable 259 = static_cast<const BindSymbolInfo*>( ut::AddOffsetToPtr( exeInfo, exeInfo->bindSymbolOffset ) ); 260 const char* stringTable = static_cast<const char*>( ut::AddOffsetToPtr( exeInfo, exeInfo->stringOffset ) ); 261 262 s32 targetIndex = 0; 263 264 switch ( symbolType ) 265 { 266 case SYMBOL_TYPE_INPUT: { targetIndex = BEGIN_INPUT + index; } break; 267 case SYMBOL_TYPE_FLOAT: { targetIndex = BEGIN_FLOAT + index; } break; 268 case SYMBOL_TYPE_INT : { targetIndex = BEGIN_INT + index; } break; 269 case SYMBOL_TYPE_BOOL : { targetIndex = BEGIN_BOOL + index; } break; 270 default: NW_FATAL_ERROR("Unknown symbolType"); 271 } 272 273 for (int i = 0; i < static_cast<int>(exeInfo->bindSymbolCount); ++i) 274 { 275 const BindSymbolInfo& info = bindSymbolInfoTable[ i ]; 276 277 s32 symbolIndex = static_cast<s32>( info.regIndex & 0x0000ffff ); 278 279 if (symbolIndex == targetIndex) 280 { 281 return &stringTable[ info.nameIndex ]; 282 } 283 } 284 285 return NULL; 286 } 287 288 //--------------------------------------------------------------------------- 289 //! @brief トータルのシンボル数を取得します。 290 //! 291 //! @param[in] shaderIndex シェーダインデックスです。 292 //! @param[in] symbolType レジスタの種類です。 293 //! 294 //! @return 入力タイプ 295 //--------------------------------------------------------------------------- SearchBinadSymbolCount(s32 shaderIndex,SymbolType symbolType)296 int SearchBinadSymbolCount(s32 shaderIndex, SymbolType symbolType) const 297 { 298 enum 299 { 300 BEGIN_INPUT = 0, END_INPUT = 15, 301 BEGIN_FLOAT = 16, END_FLOAT = 111, 302 BEGIN_INT = 112, END_INT = 119, 303 BEGIN_BOOL = 120, END_BOOL = 135, 304 END_SYMBOL = 136 305 }; 306 307 // 出力属性情報 308 struct BindSymbolInfo 309 { 310 u32 nameIndex; 311 u32 regIndex; 312 }; 313 314 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 315 316 const BindSymbolInfo* bindSymbolInfoTable = 317 static_cast<const BindSymbolInfo*>( 318 ut::AddOffsetToPtr( exeInfo, exeInfo->bindSymbolOffset ) 319 ); 320 321 s32 count = 0; 322 323 for (int i = 0; i < static_cast<int>(exeInfo->bindSymbolCount); ++i) 324 { 325 const BindSymbolInfo& info = bindSymbolInfoTable[ i ]; 326 327 s32 symbolIndex = static_cast<s32>( info.regIndex & 0x0000ffff ); 328 329 switch ( symbolType ) 330 { 331 case SYMBOL_TYPE_INPUT: 332 if (BEGIN_INPUT <= symbolIndex && symbolIndex <= END_INPUT) 333 { 334 ++count; 335 } 336 break; 337 case SYMBOL_TYPE_FLOAT: 338 if (BEGIN_FLOAT <= symbolIndex && symbolIndex <= END_FLOAT) 339 { 340 ++count; 341 } 342 break; 343 case SYMBOL_TYPE_INT: 344 if (BEGIN_INT <= symbolIndex && symbolIndex <= END_INT) 345 { 346 ++count; 347 } 348 break; 349 case SYMBOL_TYPE_BOOL: 350 if (BEGIN_BOOL <= symbolIndex && symbolIndex <= END_BOOL) 351 { 352 ++count; 353 } 354 break; 355 default: NW_FATAL_ERROR("Unknown symbolType"); 356 } 357 } 358 359 return count; 360 } 361 362 363 //--------------------------------------------------------------------------- 364 //! @brief 頂点 bool レジスタの定数値を取得します。 365 //! 366 //! @param[in] shaderIndex シェーダインデックスです。 367 //! 368 //! @return 対応するシェーダプログラムの定数 bool 値を取得します。 369 //--------------------------------------------------------------------------- GetBoolConstant(s32 shaderIndex)370 u32 GetBoolConstant(s32 shaderIndex) const 371 { 372 enum { TYPE_BOOL = 0, TYPE_INT = 1, TYPE_FLOAT = 2 }; 373 374 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 375 376 // 定数レジスタ情報 377 struct SetupInfo 378 { 379 u16 type; 380 u16 index; 381 u32 value[4]; 382 }; 383 384 const SetupInfo* setupInfoTable = 385 static_cast<const SetupInfo*>( ut::AddOffsetToPtr( exeInfo, exeInfo->setupOffset) ); 386 387 u32 boolMap = 0; 388 389 for ( int i = 0; i < static_cast<int>(exeInfo->setupCount); ++i ) 390 { 391 const SetupInfo& info = setupInfoTable[ i ]; 392 const u32* value = info.value; 393 394 if (info.type == TYPE_BOOL) 395 { 396 boolMap |= (value[ 0 ] & 0x1) << info.index; 397 } 398 } 399 400 return boolMap; 401 } 402 403 //--------------------------------------------------------------------------- 404 //! @brief シェーダのアトリビュート数を取得します。 405 //! 406 //! @param[in] shaderIndex シェーダインデックスです。 407 //! 408 //! @return 対応するシェーダプログラムのアトリビュート数を取得します。 409 //--------------------------------------------------------------------------- GetInputRegisterNum(s32 shaderIndex)410 u32 GetInputRegisterNum(s32 shaderIndex) const 411 { 412 enum { MAX_INPUT = 16 }; // ジオメトリシェーダは 16まで。 413 414 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo( shaderIndex ); 415 416 u32 mask = exeInfo->inputMask; 417 s32 count = 0; 418 419 for (int i = 0; i < 16; ++i) 420 { 421 if (mask & (1 << i)) 422 { 423 ++count; 424 } 425 } 426 427 return count; 428 } 429 430 //--------------------------------------------------------------------------- 431 //! @brief シェーダの出力数を取得します。 432 //! 433 //! @param[in] shaderIndex シェーダインデックスです。 434 //! 435 //! @return 対応するシェーダプログラムの入力数を取得します。 436 //--------------------------------------------------------------------------- GetOutputRegisterNum(s32 shaderIndex)437 u32 GetOutputRegisterNum(s32 shaderIndex) const 438 { 439 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 440 441 u32 mask = exeInfo->outputMask; 442 s32 count = 0; 443 444 for (int i = 0; i < 16; ++i) 445 { 446 if (mask & (1 << i)) 447 { 448 ++count; 449 } 450 } 451 452 return count; 453 } 454 455 //--------------------------------------------------------------------------- 456 //! @brief 頂点シェーダの出力レジスタ数を取得します。 457 //! 458 //! @param[in] shaderIndex シェーダインデックスです。 459 //! @param[in] pNum 出力レジスタ数を取得する為のポインタです。 460 //! @param[in] pMask 出力レジスタマスクを取得する為のポインタです。 461 //--------------------------------------------------------------------------- GetOutputRegisterNum(s32 shaderIndex,u32 * pNum,u32 * pMask)462 void GetOutputRegisterNum(s32 shaderIndex, u32* pNum, u32* pMask) const 463 { 464 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 465 466 u32 mask = exeInfo->outputMask; 467 s32 count = 0; 468 469 for (int i = 0; i < 16; ++i) 470 { 471 if (mask & (1 << i)) 472 { 473 ++count; 474 } 475 } 476 477 if (pNum) { *pNum = u32(count); } 478 if (pMask) { *pMask = u32(mask); } 479 } 480 481 //--------------------------------------------------------------------------- 482 //! @brief シェーダの出力レジスタ数を取得します。 483 //! 484 //! @param[in] vertexIndex 頂点シェーダーのインデックスです。 485 //! @param[in] geometryIndex ジオメトリシェーダーのインデックスです。 486 //! @param[in] pNum 出力レジスタ数を取得する為のポインタです。 487 //! @param[in] pMask 出力レジスタマスクを取得する為のポインタです。 488 //--------------------------------------------------------------------------- GetShaderOutputRegisterNum(s32 vertexIndex,s32 geometryIndex,u32 * pNum,u32 * pMask)489 void GetShaderOutputRegisterNum(s32 vertexIndex, s32 geometryIndex, u32* pNum, u32* pMask) const 490 { 491 const ExeImageInfo* exeInfo = NULL; 492 493 if (geometryIndex >= 0) 494 { 495 exeInfo= this->GetShaderProgramInfo(geometryIndex); 496 } 497 else 498 { 499 exeInfo = this->GetShaderProgramInfo(vertexIndex); 500 } 501 502 NW_NULL_ASSERT( exeInfo ); 503 504 u32 mask = exeInfo->outputMask; 505 s32 count = 0; 506 507 for (int i = 0; i < 16; ++i) 508 { 509 if (mask & (1 << i)) 510 { 511 ++count; 512 } 513 } 514 515 if (pNum) { *pNum = u32(count); } 516 if (pMask) { *pMask = u32(mask); } 517 } 518 519 //--------------------------------------------------------------------------- 520 //! @brief シェーダの出力レジスタフォーマットを取得します。 521 //! 522 //! @param[in] vertexIndex 頂点シェーダーのインデックスです。 523 //! @param[in] geometryIndex ジオメトリシェーダーのインデックスです。 524 //! @param[in] pOutputFormat シェーダの出力レジスタマップを取得する為の 525 //! サイズ7の配列へのポインタです。 526 //--------------------------------------------------------------------------- GetShaderOutputRegisterMap(s32 vertexIndex,s32 geometryIndex,u32 pOutputFormat[7])527 void GetShaderOutputRegisterMap(s32 vertexIndex, s32 geometryIndex, u32 pOutputFormat[7]) const 528 { 529 // とりあえず tugal から移植しました。要確認。 530 531 enum { OUT_ATTR_INDEX_MAX = 7, OUT_ATTR_DIMENTION_MAX = 4, VS_OUT_ATTR_INDEX_MAX = 16 }; 532 533 u32 outNum = 0; 534 u32 useTex = 0; 535 u32 clock = 0; 536 u32 outMask = 0; 537 538 NW_UNUSED_VARIABLE( useTex ); 539 540 // 出力属性情報 541 struct OutmapInfo 542 { 543 u16 type; 544 u16 index; 545 u16 mask; 546 u16 reserve; 547 }; 548 549 enum { OUTPUT_REG_NUM = 7 }; 550 const ExeImageInfo* exeInfo = NULL; 551 552 if (geometryIndex >= 0) 553 { 554 exeInfo = this->GetShaderProgramInfo(geometryIndex); 555 } 556 else 557 { 558 exeInfo = this->GetShaderProgramInfo(vertexIndex); 559 } 560 561 NW_NULL_ASSERT( exeInfo ); 562 563 const OutmapInfo* outmapInfoTable = static_cast<const OutmapInfo*>( ut::AddOffsetToPtr( exeInfo, exeInfo->outmapOffset ) ); 564 565 if ( pOutputFormat ) 566 { 567 for ( int outputIndex = 0; outputIndex < OUTPUT_REG_NUM; ++outputIndex ) 568 { 569 pOutputFormat[ outputIndex ] = 0x1f1f1f1f; 570 571 for ( int i = 0; i < static_cast<int>(exeInfo->outmapCount); ++i ) 572 { 573 u32 c = 0; 574 const OutmapInfo& outmapInfo = outmapInfoTable[ i ]; 575 576 for ( int j = 0; outmapInfo.index == outputIndex && j < OUT_ATTR_DIMENTION_MAX; ++j ) 577 { 578 if ( ( outmapInfo.mask & ( 1 << j ) ) == 0 ) { continue; } 579 580 int value = 0x1f; 581 switch ( outmapInfo.type ) 582 { 583 case 0 : 584 { 585 value = 0x00 + c++; 586 if (c == 2) { clock |= 1 << 0; } 587 } 588 break; // position 589 case 1 : 590 { 591 value = 0x04 + c++; 592 clock |= 1 << 24; 593 } 594 break; // quaternion 595 case 2 : 596 { 597 value = 0x08 + c++; 598 clock |= 1 << 1; 599 } 600 break; // color 601 case 3 : 602 { 603 if (c < 2) { value = 0x0c + c++; } 604 useTex = 1; 605 clock |= 1 << 8; 606 } 607 break; // texcoord0 608 case 4 : 609 { 610 value = 0x10; 611 useTex = 1; 612 clock |= 3 << 16; 613 } 614 break; // texcoord0w 615 case 5 : 616 { 617 if (c < 2) { value = 0x0e + c++; } 618 useTex = 1; 619 clock |= 1 << 9; 620 } 621 break; // texcoord1 622 case 6 : 623 { 624 if (c < 2) { value = 0x16 + c++; } 625 useTex = 1; 626 clock |= 1 << 10; 627 } 628 break; // texcoord2 629 case 8 : 630 { 631 if (c < 3) { value = 0x12 + c++; } 632 clock |= 1 << 24; 633 } 634 break; // view 635 } 636 637 pOutputFormat[ outputIndex ] = pOutputFormat[ outputIndex ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 ); 638 } 639 } 640 641 if (pOutputFormat[ outputIndex ] != 0x1f1f1f1f) 642 { 643 outMask |= ( 1 << outputIndex ); 644 ++outNum; 645 } 646 } 647 } 648 } 649 650 //--------------------------------------------------------------------------- 651 //! @brief 頂点シェーダの開始アドレスを取得します。 652 //! 653 //! @param[in] shaderIndex シェーダインデックスです。 654 //! 655 //! @return 頂点シェーダの開始アドレスです。 656 //--------------------------------------------------------------------------- GetEntryAddress(s32 shaderIndex)657 u32 GetEntryAddress(s32 shaderIndex) const 658 { 659 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 660 661 return exeInfo->mainAddress; 662 } 663 664 //--------------------------------------------------------------------------- 665 //! @brief ジオメトリシェーダのデータモードを取得します。 666 //! 667 //! @param[in] shaderIndex シェーダインデックスです。 668 //! 669 //! @return ジオメトリシェーダのデータモードです。 670 //--------------------------------------------------------------------------- GetGeometryDataMode(s32 shaderIndex)671 u32 GetGeometryDataMode(s32 shaderIndex) const 672 { 673 NW_ASSERT( this->IsGeometryShader( shaderIndex ) ); 674 675 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 676 677 return exeInfo->gsDataMode; 678 } 679 680 //--------------------------------------------------------------------------- 681 //! @brief ジオメトリシェーダの gs_main_vertex_num の値 を取得します。 682 //! 683 //! @param[in] shaderIndex シェーダインデックスです。 684 //! 685 //! @return ジオメトリシェーダの gs_main_vertex_num の値です。 686 //--------------------------------------------------------------------------- GetGeometryMainVertexNum(s32 shaderIndex)687 u32 GetGeometryMainVertexNum(s32 shaderIndex) const 688 { 689 NW_ASSERT( this->IsGeometryShader( shaderIndex ) ); 690 691 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 692 693 return exeInfo->gsPatchSize; 694 } 695 696 //--------------------------------------------------------------------------- 697 //! @brief ジオメトリシェーダの gs_patch_size の値を取得します。 698 //! 699 //! @param[in] shaderIndex シェーダインデックスです。 700 //! 701 //! @return ジオメトリシェーダのスタートインデックスです。 702 //--------------------------------------------------------------------------- GetGeometryPatchSize(s32 shaderIndex)703 u32 GetGeometryPatchSize(s32 shaderIndex) const 704 { 705 NW_ASSERT( this->IsGeometryShader( shaderIndex ) ); 706 707 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 708 709 return exeInfo->gsVertexNum; 710 } 711 712 //--------------------------------------------------------------------------- 713 //! @brief ジオメトリシェーダのスタートインデックスを取得します。 714 //! 715 //! @param[in] shaderIndex シェーダインデックスです。 716 //! 717 //! @return ジオメトリシェーダのスタートインデックスです。 718 //--------------------------------------------------------------------------- GetGeometryStartIndex(s32 shaderIndex)719 u32 GetGeometryStartIndex(s32 shaderIndex) const 720 { 721 NW_ASSERT( this->IsGeometryShader( shaderIndex ) ); 722 723 const ExeImageInfo* exeInfo = this->GetShaderProgramInfo(shaderIndex); 724 725 return exeInfo->gsVertexStartIndex; 726 } 727 728 //@} 729 730 //--------------------------------------------------------------------------- 731 //! @brief シェーダバイナリの解析をおこないます。 732 //--------------------------------------------------------------------------- 733 void AnalyzeBinary(); 734 735 private: 736 enum 737 { 738 EXE_IMAGE_MAX = 32, 739 SWIZZLE_PATTERN_MAX = 128, 740 DUMMY_DATA_NUM_251 = 10, 741 DUMMY_DATA_NUM_200 = 30, 742 PADDING_DATA = 0xead0fead 743 }; 744 745 // シェーダバイナリの実行イメージ情報のヘッダ構造体です。 746 struct ExeImageInfo 747 { 748 u32 signature; 749 u16 version; 750 u8 isGeometryShader; 751 u8 outputMaps; 752 u32 mainAddress; 753 u32 endAddress; 754 u16 inputMask; 755 u16 outputMask; 756 u8 gsDataMode; 757 u8 gsVertexStartIndex; 758 u8 gsPatchSize; 759 u8 gsVertexNum; 760 u32 setupOffset; 761 u32 setupCount; 762 u32 labelOffset; 763 u32 labelCount; 764 u32 outmapOffset; 765 u32 outmapCount; 766 u32 bindSymbolOffset; 767 u32 bindSymbolCount; 768 u32 stringOffset; 769 u32 stringCount; 770 }; 771 772 const u32* m_pShaderBinary; 773 u32 m_ExeImageCount; 774 const ExeImageInfo* m_ExeImageInfo[ EXE_IMAGE_MAX ]; 775 const u32* m_pInstruction; 776 u32 m_InstructionCount; 777 u32 m_Swizzle[ SWIZZLE_PATTERN_MAX ]; 778 u32 m_SwizzleCount; 779 s32 m_GeometryShaderCount; 780 781 //--------------------------------------------------------------------------- 782 //! @brief シェーダプログラムの情報を取得します。 783 //! 784 //! @param[in] shaderIndex シェーダインデックスです。 785 //! 786 //! @return シェーダプログラム情報を格納した生の構造体を返します。 787 //--------------------------------------------------------------------------- GetShaderProgramInfo(s32 shaderIndex)788 const ExeImageInfo* GetShaderProgramInfo( s32 shaderIndex ) const 789 { 790 NW_ASSERT( 0 <= shaderIndex && shaderIndex < static_cast<s32>(m_ExeImageCount) ); 791 792 return m_ExeImageInfo[ shaderIndex ]; 793 } 794 795 //--------------------------------------------------------------------------- 796 //! @brief シェーダバイナリ中に含んでいる、シェーダの数を取得します。 797 //! 頂点シェーダ、ジオメトリシェーダを含めた数を返します。 798 //! リンクした main 関数の数と等しくなります。 799 //! 800 //! @return 頂点シェーダとジオメトリシェーダを合わせた数です。 801 //--------------------------------------------------------------------------- GetShaderCount()802 s32 GetShaderCount() const 803 { 804 return m_ExeImageCount; 805 } 806 807 //--------------------------------------------------------------------------- 808 //! @brief シェーダバイナリ中に含んでいる、ジオメトリシェーダーの数を取得します。 809 //! 0 であれば、このシェーダバイナリでは必ず頂点シェーダのみという事になります。 810 //! 811 //! @return ジオメトリシェーダの数です。 812 //--------------------------------------------------------------------------- GetGeometryShaderCount()813 s32 GetGeometryShaderCount() const 814 { 815 return m_GeometryShaderCount; 816 } 817 818 // プログラムロードのコマンド生成 819 void BuildProgramCommand( SafeBuffer& buffer ) const; 820 821 // Swizzle パターンロードのコマンド生成 822 void BuildSwizzleCommand( SafeBuffer& buffer ) const; 823 824 // ジオメトリシェーダー使用設定コマンドを生成 825 void BuildPrepareCommand( SafeBuffer& buffer ) const; 826 827 // 定数レジスタのコマンド生成 828 void BuildConstRegCommand( SafeBuffer& buffer, s32 shaderIndex ) const; 829 830 // シェーダー出力属性のコマンド生成 831 void BuildOutAttrCommand( SafeBuffer& buffer, s32 vertexIndex, s32 geometryIndex ) const; 832 833 // プログラムロードのコマンドサイズを取得 834 s32 GetProgramCommandSize() const; 835 // Swizzle パターンロードのコマンドサイズを取得 836 s32 GetSwizzleCommandSize() const; 837 // ジオメトリシェーダー使用設定コマンドサイズを取得 838 s32 GetPrepareCommandSize() const; 839 // 定数レジスタのコマンドサイズを取得 840 s32 GetConstRegCommandSize( s32 shaderIndex ) const; 841 // シェーダー出力属性のコマンドサイズを取得 842 s32 GetOutAttrCommandSize( s32 vertexIndex, s32 geometryIndex ) const; 843 844 // データ転送コマンドのサイズを取得 845 s32 GetLoadCommandSize( u32 count ) const; 846 847 //--------------------------------------------------------------------------- 848 //! @brief ポートレジスタに対して大量のデータを書き込みます。 849 //! 128バイト以上のデータも指定可能です。 850 //! 851 //! @param[out] buffer コマンド書き込み先のバッファです。 852 //! @param[in] regAddr 書き込み先レジスタです。 853 //! @param[in] src 書き込み元データです。 854 //! @param[in] count データ数です。(32bit で 1) 855 //--------------------------------------------------------------------------- 856 void PutLoadCommand( SafeBuffer& buffer, u32 regAddr, const u32* src, u32 count ) const; 857 858 // 頂点シェーダから、共用シェーダのミラーモードを有効にします。 859 void PutEnableMirroringShaderSetting( SafeBuffer& buffer, bool enableMirroring ) const; 860 861 //--------------------------------------------------------------------------- 862 //! @brief バッファに対して安全に書き込みをおこなうためのクラスです。 863 //--------------------------------------------------------------------------- 864 class SafeBuffer 865 { 866 public: 867 typedef SafeBuffer Self; 868 //--------------------------------------------------------------------------- 869 //! @brief コンストラクタです。 870 //! 871 //! @param[out] start バッファの先頭アドレスです。 872 //! @param[in] size バッファサイズです。 873 //--------------------------------------------------------------------------- SafeBuffer(u32 * start,s32 size)874 SafeBuffer(u32* start, s32 size) 875 : m_StartAddress( start ), 876 m_CurrentAddress( start ), 877 m_EndAddress( static_cast<u32*>( ut::AddOffsetToPtr(start, size) ) ), 878 m_IsFinished( false ) {} 879 StartAddress()880 const u32* StartAddress() const { return m_StartAddress; } EndAddress()881 const u32* EndAddress() const { return m_EndAddress; } CurrentAddress()882 const u32* CurrentAddress() const { return m_EndAddress; } BufferSize()883 s32 BufferSize() const { return ut::GetOffsetFromPtr(m_StartAddress, m_EndAddress); } UsedSize()884 s32 UsedSize() const { return ut::GetOffsetFromPtr(m_StartAddress, m_CurrentAddress); } 885 IsFinished()886 bool IsFinished() const { return m_IsFinished; } 887 888 operator const u32*() const { return m_CurrentAddress; } 889 Self& operator++() { return this->MoveAddress(sizeof(u32)); } 890 Self operator++(int) { Self tmp = *this; (void)this->MoveAddress(sizeof(u32)); return tmp; } 891 Self& operator+=(s32 count) { return this->MoveAddress(count * sizeof(u32)); } 892 893 //--------------------------------------------------------------------------- 894 //! @brief 指定したサイズのデータが書き込めるかどうかの確認をおこないます。 895 //! 残りサイズが足りない場合には、終了処理をおこない、IsFinished() が 896 //! true を返すようになります。 897 //! 898 //! @param[in] size 書き込みデータサイズです。 899 //! 900 //! @return 残り容量に問題がなければ true, 容量が足りなければ false を返します。 901 //--------------------------------------------------------------------------- VerifyWriteSize(int size)902 bool VerifyWriteSize(int size) 903 { 904 if (ut::AddOffsetToPtr(m_CurrentAddress, size) <= m_EndAddress) 905 { 906 return true; 907 } 908 else 909 { 910 m_IsFinished = true; 911 return false; 912 } 913 } 914 915 //--------------------------------------------------------------------------- 916 //! @brief データの書き込みを行ないます。 917 //! 空き容量が足りない場合には中途半端なデータの書き込みは行なわず 918 //! 負のエラーコードを返して終了します。 919 //! 容量の問題で書き込みに失敗すると、それ以降 IsFinished() が true を 920 //! 返すようになります。 921 //! 922 //! @param[in] src 書き込み元のデータです。 923 //! @param[in] size 書き込みデータサイズです。 924 //! 925 //! @return 書き込みをおこなったデータサイズを返します。 926 //! 書き込みに失敗した場合には負のエラーコードを返します。 927 //--------------------------------------------------------------------------- Write(const u32 * src,s32 size)928 s32 Write(const u32* src, s32 size) 929 { 930 if (size <= 0) { return -1; } 931 if (!this->VerifyWriteSize(size)) { return -1; } 932 nw::os::MemCpy(m_CurrentAddress, src, size); 933 this->MoveAddress(size); 934 935 return size; 936 } 937 Write(u32 src)938 s32 Write(u32 src) 939 { 940 if (!this->VerifyWriteSize(sizeof(u32))) { return -1; } 941 *m_CurrentAddress = src; 942 ++m_CurrentAddress; 943 return sizeof(u32); 944 } 945 946 private: 947 u32* m_StartAddress; 948 u32* m_CurrentAddress; 949 u32* m_EndAddress; 950 bool m_IsFinished; 951 MoveAddress(s32 size)952 Self& MoveAddress(s32 size) 953 { 954 m_CurrentAddress = static_cast<u32*>( ut::AddOffsetToPtr(m_CurrentAddress, size) ); 955 NW_ASSERT(m_CurrentAddress <= m_EndAddress); 956 return *this; 957 } 958 }; 959 }; 960 961 } // namespace gfx 962 } // namespace nw 963 964 #endif // NW_GFX_SHADERBINARYINFO_H_ 965