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