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