1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: gr_Utility.h 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: 26237 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NN_GR_UTILITY_H_ 17 #define NN_GR_UTILITY_H_ 18 19 #include <nn.h> 20 #include <nn/types.h> 21 #include <nn/gx.h> 22 #include <nn/gx/CTR/gx_CommandAccess.h> 23 24 #include <nn/gr/CTR/gr_Prefix.h> 25 26 namespace nn 27 { 28 namespace gr 29 { 30 namespace CTR 31 { 32 33 //------------------------------------------------------------------------------ 34 35 /*! 36 @brief 3x4行列をwHzyxの順に逆転してコピーします。(ヘッダーあり) 37 38 @param[in] dst 結果を書き込む先のポインタです。 39 @param[in] src 34行列です。 40 @param[in] header ヘッダです。 41 */ 42 void CopyMtx34WithHeader( 43 f32* dst, 44 const nn::math::MTX34* src, 45 u32 header ); 46 47 /*! 48 @brief 4x4行列をwHzyxの順に逆転してコピーします。(ヘッダーあり) 49 50 @param[in] dst 結果を書き込む先のポインタです。 51 @param[in] src 44行列です。 52 @param[in] header ヘッダです。 53 */ 54 void CopyMtx44WithHeader( 55 f32* dst, 56 const nn::math::MTX44* src, 57 u32 header ); 58 59 //------------------------------------------------------------------------------------ 60 61 /*! 62 @brief 34行列を頂点シェーダのユニフォームにセットするコマンドを生成します。 63 64 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 65 @param[in] location レジスタの場所です。 66 @param[in] mtx34 34行列です。 67 68 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 69 */ MakeUniformCommandVS(u32 * command,u8 location,const nn::math::MTX34 & mtx34)70 inline u32* MakeUniformCommandVS( u32* command, u8 location, const nn::math::MTX34& mtx34 ) 71 { 72 *command++ = 0x80000000 | location; 73 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_FLOAT_ADDR ); 74 CopyMtx34WithHeader( (f32*)command, &mtx34, PICA_CMD_HEADER_VS_F32( 3 ) ); 75 return command + 14; 76 } 77 78 //------------------------------------------------------------------------------------ 79 80 /*! 81 @brief 44行列を頂点シェーダのユニフォームにセットするコマンドを生成します。 82 83 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 84 @param[in] location レジスタの場所です。 85 @param[in] mtx44 44行列です。 86 87 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 88 */ MakeUniformCommandVS(u32 * command,u8 location,const nn::math::MTX44 & mtx44)89 inline u32* MakeUniformCommandVS( u32* command, u8 location, const nn::math::MTX44& mtx44 ) 90 { 91 *command++ = 0x80000000 | location; 92 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_FLOAT_ADDR ); 93 CopyMtx44WithHeader( (f32*)command, &mtx44, PICA_CMD_HEADER_VS_F32( 4 ) ); 94 return command + 18; 95 } 96 97 //------------------------------------------------------------------------------------ 98 99 /*! 100 @brief ベクトルを頂点シェーダのユニフォームにセットするコマンドを生成します。 101 102 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 103 @param[in] location レジスタの場所です。 104 @param[in] vec4 4次元のベクトルです。 105 106 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 107 */ MakeUniformCommandVS(u32 * command,u8 location,const nn::math::VEC4 & vec4)108 inline u32* MakeUniformCommandVS( u32* command, u8 location, const nn::math::VEC4& vec4 ) 109 { 110 *command++ = 0x80000000 | location; 111 *command++ = PICA_CMD_HEADER_BURSTSEQ( PICA_REG_VS_FLOAT_ADDR, 5 ); 112 *command++ = nn::math::F32AsU32( vec4.w ); 113 *command++ = nn::math::F32AsU32( vec4.z ); 114 *command++ = nn::math::F32AsU32( vec4.y ); 115 *command++ = nn::math::F32AsU32( vec4.x ); 116 return command; 117 } 118 119 120 //------------------------------------------------------------------------------------ 121 122 /*! 123 @brief ベクトルの配列を頂点シェーダのユニフォームにセットするコマンドを生成します。 124 125 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 126 @param[in] location レジスタの場所です。 127 @param[in] vec4 4次元のベクトルの配列です。 128 @param[in] num 配列のサイズです。 129 130 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 131 */ MakeUniformCommandVS(u32 * command,u8 location,const nn::math::VEC4 vec4[],const int num)132 inline u32* MakeUniformCommandVS( u32* command, u8 location, const nn::math::VEC4 vec4[], const int num ) 133 { 134 *command++ = 0x80000000 | location; 135 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_FLOAT_ADDR ); 136 *command++ = nn::math::F32AsU32( vec4[0].w ); 137 *command++ = PICA_CMD_HEADER_VS_F32( num ); 138 *command++ = nn::math::F32AsU32( vec4[0].z ); 139 *command++ = nn::math::F32AsU32( vec4[0].y ); 140 *command++ = nn::math::F32AsU32( vec4[0].x ); 141 142 for ( int i = 1; i < num; ++i ) 143 { 144 *command++ = nn::math::F32AsU32( vec4[i].w ); 145 *command++ = nn::math::F32AsU32( vec4[i].z ); 146 *command++ = nn::math::F32AsU32( vec4[i].y ); 147 *command++ = nn::math::F32AsU32( vec4[i].x ); 148 } 149 150 *command++ = 0; // padding 151 152 return command; 153 } 154 155 //------------------------------------------------------------------------------------ 156 157 /*! 158 @brief 整数を頂点シェーダのユニフォームにセットするコマンドを生成します。 159 160 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 161 @param[in] location レジスタの場所です。 162 @param[in] x x 座標の値です。 163 @param[in] y y 座標の値です。 164 @param[in] z z 座標の値です。 165 166 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 167 */ MakeUniformCommandVS(u32 * command,u8 location,u8 x,u8 y,u8 z)168 inline u32* MakeUniformCommandVS( u32* command, u8 location, u8 x, u8 y, u8 z ) 169 { 170 *command++ = PICA_CMD_DATA_VS_INT( x, y, z ); 171 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_INT0 + location ); 172 return command; 173 } 174 175 //------------------------------------------------------------------------------------ 176 177 /*! 178 @brief 34行列をジオメトリシェーダのユニフォームにセットするコマンドを生成します。 179 180 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 181 @param[in] location レジスタの場所です。 182 @param[in] mtx34 34行列です。 183 184 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 185 */ MakeUniformCommandGS(u32 * command,u8 location,const nn::math::MTX34 & mtx34)186 inline u32* MakeUniformCommandGS( u32* command, u8 location, const nn::math::MTX34& mtx34 ) 187 { 188 *command++ = 0x80000000 | location; 189 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_FLOAT_ADDR ); 190 CopyMtx34WithHeader( (f32*)command, &mtx34, PICA_CMD_HEADER_GS_F32( 3 ) ); 191 return command + 14; 192 } 193 194 //------------------------------------------------------------------------------------ 195 196 /*! 197 @brief 44行列をジオメトリシェーダのユニフォームにセットするコマンドを生成します。 198 199 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 200 @param[in] location レジスタの場所です。 201 @param[in] mtx44 44行列です。 202 203 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 204 */ MakeUniformCommandGS(u32 * command,u8 location,const nn::math::MTX44 & mtx44)205 inline u32* MakeUniformCommandGS( u32* command, u8 location, const nn::math::MTX44& mtx44 ) 206 { 207 *command++ = 0x80000000 | location; 208 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_FLOAT_ADDR ); 209 CopyMtx44WithHeader( (f32*)command, &mtx44, PICA_CMD_HEADER_GS_F32( 4 ) ); 210 return command + 18; 211 } 212 213 //------------------------------------------------------------------------------------ 214 215 /*! 216 @brief ベクトルをジオメトリシェーダのユニフォームにセットするコマンドを生成します. 217 218 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 219 @param[in] location レジスタの場所です。 220 @param[in] vec4 4次元のベクトルです。 221 222 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 223 */ MakeUniformCommandGS(u32 * command,u8 location,const nn::math::VEC4 & vec4)224 inline u32* MakeUniformCommandGS( u32* command, u8 location, const nn::math::VEC4& vec4 ) 225 { 226 *command++ = 0x80000000 | location; 227 *command++ = PICA_CMD_HEADER_BURSTSEQ( PICA_REG_GS_FLOAT_ADDR, 5 ); 228 *command++ = nn::math::F32AsU32( vec4.w ); // a 229 *command++ = nn::math::F32AsU32( vec4.z ); // b 230 *command++ = nn::math::F32AsU32( vec4.y ); // g 231 *command++ = nn::math::F32AsU32( vec4.x ); // r 232 return command; 233 } 234 235 //------------------------------------------------------------------------------------ 236 237 /*! 238 @brief ベクトルの配列をジオメトリシェーダのユニフォームにセットするコマンドを生成します。 239 240 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 241 @param[in] location レジスタの場所です。 242 @param[in] vec4 4次元のベクトルの配列です。 243 @param[in] num 配列のサイズです。 244 245 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 246 */ MakeUniformCommandGS(u32 * command,u8 location,const nn::math::VEC4 vec4[],const int num)247 inline u32* MakeUniformCommandGS( u32* command, u8 location, const nn::math::VEC4 vec4[], const int num ) 248 { 249 *command++ = 0x80000000 | location; 250 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_FLOAT_ADDR ); 251 *command++ = nn::math::F32AsU32( vec4[0].w ); 252 *command++ = PICA_CMD_HEADER_GS_F32( num ); 253 *command++ = nn::math::F32AsU32( vec4[0].z ); 254 *command++ = nn::math::F32AsU32( vec4[0].y ); 255 *command++ = nn::math::F32AsU32( vec4[0].x ); 256 257 for ( int i = 1; i < num; ++i ) 258 { 259 *command++ = nn::math::F32AsU32( vec4[i].w ); 260 *command++ = nn::math::F32AsU32( vec4[i].z ); 261 *command++ = nn::math::F32AsU32( vec4[i].y ); 262 *command++ = nn::math::F32AsU32( vec4[i].x ); 263 } 264 265 *command++ = 0; // padding 266 267 return command; 268 } 269 270 //------------------------------------------------------------------------------------ 271 272 /*! 273 @brief 整数をジオメトリシェーダのユニフォームにセットするコマンドを生成します。 274 275 @param[in] command 描画コマンドの書き込み先の先頭アドレスです。 276 @param[in] location レジスタの場所です。 277 @param[in] x x 座標の値です。 278 @param[in] y y 座標の値です。 279 @param[in] z z 座標の値です。 280 281 @return 書き込まれた描画コマンドの終端の次のアドレスを返します。 282 */ MakeUniformCommandGS(u32 * command,u8 location,u8 x,u8 y,u8 z)283 inline u32* MakeUniformCommandGS( u32* command, u8 location, u8 x, u8 y, u8 z ) 284 { 285 *command++ = PICA_CMD_DATA_GS_INT( x, y, z ); 286 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_INT0 + location ); 287 return command; 288 } 289 290 //------------------------------------------------------------------------------------ 291 292 /*! 293 @brief float32 を u8 に変換します。 294 295 @param[in] val 変換前の値です。 296 297 @return 変換後の値です。 298 */ FloatToUnsignedByte(f32 val)299 inline u8 FloatToUnsignedByte( 300 f32 val 301 ) 302 { 303 return ( u8 )( 0.5f + ( val < 0.f ? 0.f : ( 1.f < val ? 1.f : val ) ) * ( 0xff ) ); 304 } 305 306 //------------------------------------------------------------------------------------ 307 308 /*! 309 @brief float32 を クランプせずに u8 に変換します。 310 311 @param[in] val 変換前の値です。 312 313 @return 変換後の値です 314 */ FloatToUnsignedByteNoClamp(f32 val)315 inline u8 FloatToUnsignedByteNoClamp( 316 f32 val 317 ) 318 { 319 return ( u8 )( 0.5f + val * 0xff ); 320 } 321 322 //------------------------------------------------------------------------------------ 323 324 /*! 325 @brief float32 から float16 に変換します。 326 327 @param[in] val 変換前の値です。 328 329 @return 変換後の値です 330 */ Float32ToFloat16(f32 val)331 inline u16 Float32ToFloat16( f32 val ) 332 { 333 static const int bias_ = 128 - (1 << (5 - 1)); 334 335 u32 uval_ = *(u32*)&val; 336 int e_ = (uval_ & 0x7fffffff) ? (((uval_ >> 23) & 0xff) - bias_) : 0; 337 if (e_ >= 0) 338 { 339 return ( u16 )( ((uval_ & 0x7fffff) >> (23 - 10)) | (e_ << 10) | ((uval_ >> 31) << (10 + 5)) ); 340 } 341 return ( u16 )((uval_ >> 31) << (10 + 5)); 342 } 343 344 //------------------------------------------------------------------------------------ 345 346 /*! 347 @brief float32 から float24 に変換します。 348 349 @param[in] val 変換前の値です。 350 351 @return 変換後の値です 352 */ Float32ToFloat24(f32 val)353 inline u32 Float32ToFloat24( f32 val ) 354 { 355 static const int bias_ = 128 - (1 << (7 - 1)); 356 u32 uval_ = *(unsigned*)&val; 357 s32 e_ = (uval_ & 0x7fffffff) ? (((uval_ >> 23) & 0xff) - bias_) : 0; 358 359 return e_ >= 0 ? ((uval_ & 0x7fffff) >> (23 - 16)) | (e_ << 16) | ((uval_ >> 31) << (16 + 7)) : ((uval_ >> 31) << (16 + 7)); 360 } 361 362 //------------------------------------------------------------------------------------ 363 364 /*! 365 @brief float32 から float20 に変換します。 366 367 @param[in] val 変換前の値です。 368 369 @return 変換後の値です 370 */ Float32ToFloat20(f32 val)371 inline u32 Float32ToFloat20( f32 val ) 372 { 373 static const int bias_ = 128 - (1 << (7 - 1)); 374 u32 uval_ = *(unsigned*)&val; 375 s32 e_ = (uval_ & 0x7fffffff) ? (((uval_ >> 23) & 0xff) - bias_) : 0; 376 377 return e_ >= 0 ? ((uval_ & 0x7fffff) >> (23 - 12)) | (e_ << 12) | ((uval_ >> 31) << (12 + 7)) : ((uval_ >> 31) << (12 + 7)); 378 } 379 380 //------------------------------------------------------------------------------------ 381 382 /*! 383 @brief float32 から float31 に変換します。 384 385 @param[in] val 変換前の値です。 386 387 @return 変換後の値です 388 */ Float32ToFloat31(f32 val)389 inline u32 Float32ToFloat31( f32 val ) 390 { 391 unsigned uval_, m_; 392 int e_; 393 float f_ = val; 394 static const int bias_ = 128 - (1 << (7 - 1)); 395 uval_ = *(unsigned*)&f_; 396 e_ = (uval_ & 0x7fffffff) ? (((uval_ >> 23) & 0xff) - bias_) : 0; 397 m_ = (uval_ & 0x7fffff) >> (23 - 23); 398 return e_ >= 0 ? m_ | (e_ << 23) | ((uval_ >> 31) << (23 + 7)) : ((uval_ >> 31) << (23 + 7)); 399 } 400 401 //------------------------------------------------------------------------------------ 402 403 /*! 404 @brief float32 から 符号なし fixed12 に変換します。 405 406 @param[in] val 変換前の値です。 407 408 @return 変換後の値です 409 */ Float32ToUnsignedFix12(f32 val)410 inline u32 Float32ToUnsignedFix12( f32 val ) 411 { 412 unsigned v_ = *(unsigned*)&val; 413 if( val <= 0 || (v_ & 0x7f800000) == 0x7f800000 ) 414 return 0; 415 416 unsigned uval_; 417 418 val *= 1 << (12 - 0); 419 if (val >= (1 << 12)) 420 uval_ = (1 << 12) - 1; 421 else 422 uval_ = (unsigned)(val); 423 424 return uval_; 425 } 426 427 //------------------------------------------------------------------------------------ 428 429 /*! 430 @brief float32 から 符号あり fixed12 に変換します。 431 432 @param[in] val 変換前の値です。 433 434 @return 変換後の値です 435 */ Float32ToFix12(f32 val)436 inline u32 Float32ToFix12( f32 val ) 437 { 438 unsigned v_ = *(unsigned*)&val; 439 if( val == 0.f || (v_ & 0x7f800000) == 0x7f800000 ) 440 return 0; 441 442 int ret; 443 444 val *= (1 << (12 - 1)); 445 446 if( val < 0 ) 447 { 448 ret = 1 << (12 - 1); 449 val = -val; 450 } 451 else 452 ret = 0; 453 454 if( val >= (1 << (12 - 1)) ) 455 val = (1 << (12 - 1)) - 1; 456 457 ret |= (unsigned)(val); 458 return ret; 459 } 460 461 //------------------------------------------------------------------------------------ 462 463 /*! 464 @brief float32 から fixed13 ( fraction 8) に変換します。 465 466 @param[in] val 変換前の値です。 467 468 @return 変換後の値です 469 */ Float32ToFix13Fraction8(f32 val)470 inline u32 Float32ToFix13Fraction8( f32 val ) 471 { 472 unsigned v_ = *(unsigned*)&val; 473 if( val == 0.f || (v_ & 0x7f800000) == 0x7f800000 ) 474 return 0; 475 476 val += 0.5f * (1 << 5); 477 val *= 1 << (13 - 5); 478 if (val < 0) 479 val = 0; 480 else if (val >= (1 << 13)) 481 val = (1 << 13) - 1; 482 483 return (val >= (1 << (13 - 1))) ? (unsigned)(val - (1 << (13 - 1))) : (unsigned)(val + (1 << (13 - 1))); 484 } 485 486 //------------------------------------------------------------------------------------ 487 488 /*! 489 @brief float32 から fixed11 ( fraction 8) に変換します。 490 491 @param[in] val 変換前の値です。 492 493 @return 変換後の値です 494 */ Float32ToFix13Fraction11(f32 val)495 inline u32 Float32ToFix13Fraction11( f32 val ) 496 { 497 unsigned v_ = *(unsigned*)&val; 498 if( val == 0.f || (v_ & 0x7f800000) == 0x7f800000 ) 499 return 0; 500 501 val += 0.5f * (1 << 2); 502 val *= 1 << (13 - 2); 503 if (val < 0) 504 val = 0; 505 else if (val >= (1 << 13)) 506 val = (1 << 13) - 1; 507 508 return (val >= (1 << (13 - 1))) ? (unsigned)(val - (1 << (13 - 1))) : (unsigned)(val + (1 << (13 - 1))); 509 } 510 511 //------------------------------------------------------------------------------------ 512 513 /*! 514 @brief float32 から 符号無し fixed11 に変換します。 515 */ Float32ToUnsignedFix11(f32 val)516 inline u32 Float32ToUnsignedFix11( f32 val ) 517 { 518 unsigned v_ = *(unsigned*)&val; 519 if( val <= 0 || (v_ & 0x7f800000) == 0x7f800000 ) 520 return 0; 521 522 unsigned uval_; 523 524 val *= 1 << (11 - 0); 525 if (val >= (1 << 11)) 526 uval_ = (1 << 11) - 1; 527 else 528 uval_ = (unsigned)(val); 529 530 return uval_; 531 } 532 533 //------------------------------------------------------------------------------------ 534 535 /*! 536 @brief 頂点配列の型から、バイトサイズを求めます。 537 538 @param[in] type 頂点配列の型です。 539 540 @return バイトサイズです。 541 */ PicaDataVertexAttrTypeToByteSize(const PicaDataVertexAttrType type)542 inline u32 PicaDataVertexAttrTypeToByteSize( const PicaDataVertexAttrType type ) 543 { 544 switch ( type ) 545 { 546 case PICA_DATA_SIZE_1_BYTE : return 1 * sizeof( s8 ); 547 case PICA_DATA_SIZE_1_UNSIGNED_BYTE : return 1 * sizeof( u8 ); 548 case PICA_DATA_SIZE_1_SHORT : return 1 * sizeof( s16 ); 549 case PICA_DATA_SIZE_1_FLOAT : return 1 * sizeof( f32 ); 550 case PICA_DATA_SIZE_2_BYTE : return 2 * sizeof( s8 ); 551 case PICA_DATA_SIZE_2_UNSIGNED_BYTE : return 2 * sizeof( u8 ); 552 case PICA_DATA_SIZE_2_SHORT : return 2 * sizeof( s16 ); 553 case PICA_DATA_SIZE_2_FLOAT : return 2 * sizeof( f32 ); 554 case PICA_DATA_SIZE_3_BYTE : return 3 * sizeof( s8 ); 555 case PICA_DATA_SIZE_3_UNSIGNED_BYTE : return 3 * sizeof( u8 ); 556 case PICA_DATA_SIZE_3_SHORT : return 3 * sizeof( s16 ); 557 case PICA_DATA_SIZE_3_FLOAT : return 3 * sizeof( f32 ); 558 case PICA_DATA_SIZE_4_BYTE : return 4 * sizeof( s8 ); 559 case PICA_DATA_SIZE_4_UNSIGNED_BYTE : return 4 * sizeof( u8 ); 560 case PICA_DATA_SIZE_4_SHORT : return 4 * sizeof( s16 ); 561 case PICA_DATA_SIZE_4_FLOAT : return 4 * sizeof( f32 ); 562 } 563 return 0; 564 } 565 566 } // namespace CTR 567 } // namespace gr 568 } // namespace nn 569 570 #endif // NN_GR_UTILITY_H_ 571