1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gr_Shader.cpp
4 
5   Copyright (C)2010 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 35551 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/gr/CTR/gr_Shader.h>
17 
18 namespace nn
19 {
20     namespace gr
21     {
22         namespace CTR
23         {
Shader(void)24             Shader::Shader( void ) :
25             m_VtxShaderIndex( 0 ), m_GeoShaderIndex( - 1 ),
26             m_ExeImageInfoNum( 0 ),
27             m_InstructionCount( 0 ), m_SwizzleCount( 0 ),
28             m_DrawMode( PICA_DATA_DRAW_TRIANGLES ),
29             m_VtxShaderBoolMapUniform( 0 ), m_GeoShaderBoolMapUniform( 0 ),
30             m_CmdCacheOutAttrNum( 0 ),
31             m_CmdCacheVtxConstNum( 0 ), m_CmdCacheGeoConstNum( 0 )
32             {
33                 for ( u32 index = 0; index <  OUT_ATTR_COMMAND_MAX; index++)
34                 {
35                     m_CmdCacheOutAttr[ index ] = 0;
36                 }
37 
38                 for ( u32 index = 0; index < CONST_REG_COMMAND_MAX; index++)
39                 {
40                     m_CmdCacheVtxConst[ index ] = 0;
41                     m_CmdCacheGeoConst[ index ] = 0;
42                 }
43             }
44 
SetupBinary(const void * shader_binary,const int vtx_shader_index,const int geo_shader_index)45             void Shader::SetupBinary( const void* shader_binary, const int vtx_shader_index, const int geo_shader_index )
46             {
47                 const bit32* binary = reinterpret_cast< const bit32* >( shader_binary );
48                 NN_GR_ASSERT( binary != NULL );
49 
50                 NN_GR_ASSERT( *binary == 0x424C5644 ); // DVLB
51                 ++binary;
52 
53                 NN_GR_ASSERT( *binary < EXE_IMAGE_MAX );
54                 m_ExeImageInfoNum = *binary;
55                 ++binary;
56 
57                 m_VtxShaderIndex = vtx_shader_index;
58                 m_GeoShaderIndex = geo_shader_index;
59                 m_VtxShaderBoolMapUniform = 0;
60                 m_GeoShaderBoolMapUniform = 0;
61 
62                 for ( int i = 0; i < m_ExeImageInfoNum; ++i )
63                 {
64                     m_ExeImageInfo[ i ] = reinterpret_cast< const ExeImageInfo* >( (u8*)shader_binary + *binary );
65                     NN_GR_ASSERT( m_ExeImageInfo[ i ]->signature == 0x454c5644 ); // DVLP
66                     ++binary;
67                 }
68 
69                 const bit32* package_info = binary;
70                 NN_GR_ASSERT( *binary == 0x504C5644 ); // DVLP
71                 ++binary;
72                 ++binary;
73 
74                 m_Instruction = reinterpret_cast< const bit32* >( (u8*)package_info + *binary );
75                 ++binary;
76 
77                 m_InstructionCount = *binary;
78                 ++binary;
79 
80                 const bit32* swizzle = reinterpret_cast< const bit32* >( (u8*)package_info + *binary );
81                 ++binary;
82 
83                 m_SwizzleCount = *binary;
84                 NN_GR_ASSERT( m_SwizzleCount < SWIZZLE_PATTERN_MAX );
85                 ++binary;
86 
87                 for ( int i = 0; i < m_SwizzleCount; i++ )
88                 {
89                     m_Swizzle[ i ] = swizzle[ i * 2 ] ;
90                 }
91                 // 範囲テスト
92                 NN_GR_ASSERT( 0 <= m_VtxShaderIndex && m_VtxShaderIndex < m_ExeImageInfoNum );
93 
94                 // バイナリとの整合性のテスト
95                 NN_GR_ASSERT( !m_ExeImageInfo[ m_VtxShaderIndex ]->isGeoShader );
96 
97                 if ( IsEnableGeoShader() )
98                 {
99                     // 範囲テスト
100                     NN_GR_ASSERT( m_GeoShaderIndex < GetShaderNum() );
101 
102                     // バイナリとの整合性のテスト
103                     NN_GR_ASSERT( m_ExeImageInfo[ m_GeoShaderIndex ]->isGeoShader );
104 
105                     // 定数レジスタのコマンド生成
106                     m_CmdCacheGeoConstNum = MakeConstRgCommand_( m_CmdCacheGeoConst, true ) - m_CmdCacheGeoConst;
107                     NN_GR_ASSERT( m_CmdCacheGeoConstNum <= CONST_REG_COMMAND_MAX );
108                 }
109 
110                 // 定数レジスタのコマンド生成
111                 m_CmdCacheVtxConstNum = MakeConstRgCommand_( m_CmdCacheVtxConst, false ) - m_CmdCacheVtxConst;
112                 NN_GR_ASSERT( m_CmdCacheVtxConstNum <= CONST_REG_COMMAND_MAX );
113 
114                 // 出力属性のコマンド生成
115                 m_CmdCacheOutAttrNum = MakeOutAttrCommand_( m_CmdCacheOutAttr ) - m_CmdCacheOutAttr;
116                 NN_GR_ASSERT( m_CmdCacheOutAttrNum <= OUT_ATTR_COMMAND_MAX );
117             }
118 
119             //------------------------------------------------------------------------
120 
MakeFullCommand(bit32 * command) const121             bit32* Shader::MakeFullCommand( bit32* command ) const
122             {
123                 { // ジオメトリシェーダー使用設定コマンドなどの生成
124                     command = MakePrepareCommand( command );
125                 }
126 
127                 if ( IsEnableGeoShader() )
128                 { // ジオメトリシェーダー
129                     command = MakeGeoProgramCommand( command );
130                     command = MakeGeoSwizzleCommand( command );
131                     command = MakeGeoConstRgCommand( command );
132                     command = MakeGeoBoolMapCommand( command );
133                 }
134 
135                 { // 頂点シェーダー
136                     command = MakeVtxProgramCommand( command );
137                     command = MakeVtxSwizzleCommand( command );
138                     command = MakeVtxConstRgCommand( command );
139                     command = MakeVtxBoolMapCommand( command );
140                 }
141 
142                 { // 出力属性(outmap)関連
143                     command = MakeOutAttrCommand( command );
144                 }
145 
146                 return command;
147             }
148 
149             //------------------------------------------------------------------------
150 
MakeDisableCommand(bit32 * command)151             bit32* Shader::MakeDisableCommand( bit32* command )
152             {
153                 const bool isEnableGeometryShader = false;
154                 const PicaDataDrawMode drawMode   = PICA_DATA_DRAW_TRIANGLES;
155 
156                 command = MakeShaderModeCommand_( command,
157                                                   isEnableGeometryShader,
158                                                   drawMode );
159 
160                 return command;
161             }
162 
163             //------------------------------------------------------------------------
164 
MakePrepareCommand(bit32 * command) const165             bit32* Shader::MakePrepareCommand( bit32* command ) const
166             {
167                 bool isEnableGeoShader    = IsEnableGeoShader();
168                 PicaDataDrawMode drawMode = m_DrawMode;
169 
170                 command =
171                     MakeShaderModeCommand_( command,
172                                             isEnableGeoShader,
173                                             drawMode );
174 
175                 return command;
176             }
177 
178             //------------------------------------------------------------------------
179 
MakeVtxProgramCommand(bit32 * command) const180             bit32* Shader::MakeVtxProgramCommand( bit32* command ) const
181             {
182                 int shader_index = GetVtxShaderIndex();
183                 bit32 reg_addr     = PICA_REG_VS_PROG_ADDR;        // 0x2cb
184                 bit32 reg_load     = PICA_REG_VS_PROG_DATA0;       // 0x2cc
185                 bit32 reg_end      = PICA_REG_VS_PROG_UPDATE_END;  // 0x2bf
186 
187                 { // プログラムコードのロードアドレスを設定
188                     *command++ = 0;
189                     *command++ = PICA_CMD_HEADER_SINGLE( reg_addr );
190                 }
191 
192                 { // プログラムコードのロード
193                     NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum );
194 
195                     const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
196 
197                     NN_UNUSED_VAR( exe_info );
198 
199                     u32 instructionCount = m_InstructionCount;
200                     if ( instructionCount > 512 )
201                     {
202                         instructionCount = 512;
203                     }
204 
205                     command = MakeLoadCommand_( command, reg_load,
206                                                 m_Instruction,
207                                                 m_InstructionCount < 512 ? m_InstructionCount : 512 );
208                 }
209 
210                 { // プログラム更新の完了通知
211                     *command++ = 1;
212                     *command++ = PICA_CMD_HEADER_SINGLE( reg_end );
213                 }
214 
215                 return command;
216             }
217 
218             //------------------------------------------------------------------------
219 
MakeGeoProgramCommand(bit32 * command) const220             bit32* Shader::MakeGeoProgramCommand( bit32* command ) const
221             {
222                 int shader_index = GetGeoShaderIndex();
223                 bit32 reg_addr     = PICA_REG_GS_PROG_ADDR;        // 0x29b
224                 bit32 reg_load     = PICA_REG_GS_PROG_DATA0;       // 0x29c
225                 bit32 reg_end      = PICA_REG_GS_PROG_UPDATE_END;  // 0x28f
226 
227                 { // プログラムコードのロードアドレスを設定
228                     *command++ = 0;
229                     *command++ = PICA_CMD_HEADER_SINGLE( reg_addr );
230                 }
231 
232                 { // プログラムコードのロード
233                     NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum );
234 
235                     const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
236 
237                     NN_UNUSED_VAR( exe_info );
238 
239                     command = MakeLoadCommand_( command, reg_load,
240                                                 m_Instruction,
241                                                 m_InstructionCount );
242                 }
243 
244                 { // プログラム更新の完了通知
245                     *command++ = 1;
246                     *command++ = PICA_CMD_HEADER_SINGLE( reg_end );
247                 }
248 
249                 return command;
250             }
251 
252             //------------------------------------------------------------------------
253 
MakeShaderModeCommand_(bit32 * command,const bool isEnableGeoShader,const PicaDataDrawMode drawMode)254             bit32* Shader::MakeShaderModeCommand_( bit32* command,
255                                                    const bool isEnableGeoShader,
256                                                    const PicaDataDrawMode drawMode )
257             {
258                 // 0x25e[9:8] への設定
259                 {
260                     if ( isEnableGeoShader )
261                     {
262                         *command++ = PICA_DATA_DRAW_GEOMETRY_PRIMITIVE << 8;
263                     }
264                     else
265                     {
266                         *command++ = drawMode << 8;
267                     }
268                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 2 );
269                 }
270 
271                 // 0x251 へのダミーコマンド
272                 {
273                     command = MakeDummyCommand_( command, PICA_REG_VS_OUT_REG_NUM2, DUMMY_DATA_NUM_251 );
274                 }
275 
276                 // 0x200 へのダミーコマンド
277                 {
278                     command = MakeDummyCommand_( command, PICA_REG_VERTEX_ATTR_ARRAYS_BASE_ADDR, DUMMY_DATA_NUM_200 );
279                 }
280 
281                 // 0x229[1:0] ジオメトリシェーダーの有効、無効を設定
282                 {
283                     *command++ = isEnableGeoShader ? 2 : 0;
284                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 1 );
285                 }
286 
287                 // 0x200 へのダミーコマンド
288                 {
289                     command = MakeDummyCommand_( command, PICA_REG_VERTEX_ATTR_ARRAYS_BASE_ADDR, DUMMY_DATA_NUM_200 );
290                 }
291 
292                 // 0x244 ジオメトリシェーダーの設定を頂点シェーダーと共有するかどうか
293                 {
294                     *command++ = isEnableGeoShader ? 1 : 0;
295                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_COM_MODE, 1 );
296                 }
297 
298                 return command;
299             }
300 
301             //------------------------------------------------------------------------
302 
MakeConstRgCommand_(bit32 * command,const bool is_geometry_shader)303             bit32* Shader::MakeConstRgCommand_( bit32* command,
304                                                 const bool is_geometry_shader )
305             {
306                 int  shader_index = GetVtxShaderIndex();
307                 bit32  reg_float    = PICA_REG_VS_FLOAT_ADDR; // 0x2c0
308                 bit32  reg_integer  = PICA_REG_VS_INT0;       // 0x2b1
309                 bit32* boolMap      = &m_VtxShaderBoolMapUniform;
310 
311                 if ( is_geometry_shader )
312                 {
313                     shader_index = GetGeoShaderIndex();
314                     reg_float    = PICA_REG_GS_FLOAT_ADDR; // 0x290
315                     reg_integer  = PICA_REG_GS_INT0;       // 0x281
316                     boolMap      = &m_GeoShaderBoolMapUniform;
317                 }
318 
319                 // プログラム情報
320                 NN_GR_ASSERT( 0 <= shader_index && shader_index < m_ExeImageInfoNum );
321                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
322 
323                 // 定数レジスタ情報
324                 struct SetupInfo { u16 type; u16 index; bit32 value[4]; };
325 
326                 const SetupInfo* setupInfo =
327                     reinterpret_cast< const SetupInfo* >(
328                         reinterpret_cast< const u8* >( exe_info ) + exe_info->setupOffset );
329 
330                 // 定数レジスタのコマンド生成
331                 for ( int i = 0; i < exe_info->setupCount; ++i )
332                 {
333                     const SetupInfo& info = setupInfo[ i ];
334                     const bit32* value = info.value;
335 
336                     switch ( info.type )
337                     {
338                     case 0 : // bool register setup
339                         *boolMap |= ( info.value[ 0 ] << info.index ) & ( 1 << info.index );
340                         break;
341 
342                     case 1 : // integer register setup
343                         *command++ = value[ 0 ] | value[ 1 ] <<  8 | value[ 2 ] << 16 | value[ 3 ] << 24;
344                         *command++ = PICA_CMD_HEADER_SINGLE( reg_integer + info.index );
345                         break;
346 
347                     case 2 : // float register setup
348                         *command++ = info.index;
349                         *command++ = PICA_CMD_HEADER_BURSTSEQ( reg_float, 4 );
350                         *command++ = ( value[ 3 ] <<  8 & 0xffffff00 ) | ( value[ 2 ] >> 16 & 0x000000ff );
351                         *command++ = ( value[ 2 ] << 16 & 0xffff0000 ) | ( value[ 1 ] >>  8 & 0x0000ffff );
352                         *command++ = ( value[ 1 ] << 24 & 0xff000000 ) | ( value[ 0 ] >>  0 & 0x00ffffff );
353                         *command++ = PADDING_DATA; // padding
354                         break;
355                     }
356                 }
357 
358                 return command;
359             }
360 
361             //------------------------------------------------------------------------
362 
MakeOutAttrCommand_(bit32 * command)363             bit32* Shader::MakeOutAttrCommand_( bit32* command )
364             {
365                 // 出力属性の設定
366                 // ジオメトリシェーダーが有効な場合、
367                 // 出力属性は、ジオメトリシェーダーについて設定をおこなう
368                 const int shader_index = IsEnableGeoShader() ? GetGeoShaderIndex() : GetVtxShaderIndex();
369                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
370 
371                 enum
372                 {
373                        OUT_ATTR_INDEX_MAX     = 7,
374                        OUT_ATTR_DIMENTION_MAX = 4,
375                        OUT_ATTR_BUFFER_MAX    = 16 * 4,
376                        VS_OUT_ATTR_INDEX_MAX  = 16
377                 };
378 
379                 // 出力属性情報
380                 struct OutmapInfo { u16 type; u16 index; u16 mask; u16 reserve; };
381 
382                 u32 outNum  = 0;
383                 bit32 useTex  = 0;
384                 bit32 clock   = 0;
385                 bit32 outMask = 0;
386                 bit32 attr[ OUT_ATTR_INDEX_MAX ];
387 
388                 { // 出力属性の設定をもとめる
389 
390                     // プログラム情報
391                     const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
392 
393 
394                     // 実際の出力属性情報.
395                     OutmapInfo outmap_buffer[ OUT_ATTR_BUFFER_MAX ];
396                     s32 outMapBufferCount = 0;
397 
398                     // マージ.
399                     if ( IsEnableGeoShader() && exe_info->outputMaps )
400                     {
401                         bit32 gs_copy_mask = 0;
402                         bit32 vs_copy_mask = 0;
403                         // GS出力属性情報
404                         const OutmapInfo* outmapInfo =
405                             reinterpret_cast< const OutmapInfo* >(
406                                 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset );
407                         // VSプログラム情報
408                         int vtx_shader_index = GetVtxShaderIndex();
409                         NN_GR_ASSERT(  0 <= vtx_shader_index && vtx_shader_index < m_ExeImageInfoNum );
410                         const ExeImageInfo* vtx_exe_info = m_ExeImageInfo[ vtx_shader_index ];
411 
412                         // VS出力属性情報
413                         const OutmapInfo* vtxOutmapInfo =
414                             reinterpret_cast< const OutmapInfo* >(
415                                 reinterpret_cast< const u8* >( vtx_exe_info ) + vtx_exe_info->outMapOffset );
416 
417                         // 最初にVSとGS両方で指定されているものを設定.
418                         NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX );
419                         for( s32 g = 0; g < exe_info->outMapCount; ++g )
420                         {
421                             // GS の generic 属性( 値 9 ) は除きます
422                             if ( ( outmapInfo[ g ].type >= 0 ) &&
423                                  ( outmapInfo[ g ].type <  9 ) &&
424                                  ( outmapInfo[ g ].type != 7 ) )
425                             {
426                                 for( s32 v = 0; v < vtx_exe_info->outMapCount; ++v )
427                                 {
428                                     // VS の generic 属性( 値 9 ) は除きます
429                                     if ( ( vtxOutmapInfo[ v ].type >= 0 ) &&
430                                          ( vtxOutmapInfo[ v ].type <  9 ) &&
431                                          ( vtxOutmapInfo[ v ].type != 7 ) )
432                                     {
433                                         if ( outmapInfo[ g ].type == vtxOutmapInfo[ v ].type )
434                                         {
435                                             NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_INDEX_MAX );
436                                             outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type;
437                                             outmap_buffer[ outMapBufferCount ].index = outMapBufferCount;
438                                             outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask;
439                                             gs_copy_mask |= 1 << g;
440                                             vs_copy_mask |= 1 << v;
441                                             ++outMapBufferCount;
442                                         }
443                                     }
444                                 }
445                             }
446                         }
447 
448                         // 次にGSのみで定義されているものを設定.
449                         for( s32 g = 0; g < exe_info->outMapCount; ++g )
450                         {
451                             if ( ( !( gs_copy_mask & ( 1 << g ) ) ) &&
452                                  ( outmapInfo[ g ].type >= 0 ) &&
453                                  ( outmapInfo[ g ].type < 9  ) &&
454                                  (  outmapInfo[ g ].type != 7 ) )
455                             {
456                                 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX );
457                                 outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type;
458                                 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount;
459                                 outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask;
460                                 ++outMapBufferCount;
461                             }
462                         }
463 
464                         // 最後ににVSのみで定義されているものを設定.
465                         for( s32 v = 0; v < vtx_exe_info->outMapCount; ++v )
466                         {
467                             if ( ( !( vs_copy_mask & ( 1 << v ) ) ) &&
468                                  ( vtxOutmapInfo[ v ].type >= 0 )   &&
469                                  ( vtxOutmapInfo[ v ].type < 9  )   &&
470                                  ( vtxOutmapInfo[ v ].type != 7 ) )
471                             {
472                                 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX );
473                                 outmap_buffer[ outMapBufferCount ].type = vtxOutmapInfo[ v ].type;
474                                 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount;
475                                 outmap_buffer[ outMapBufferCount ].mask = vtxOutmapInfo[ v ].mask;
476                                 ++outMapBufferCount;
477                             }
478                         }
479                     }
480                     else
481                     {
482                         // 出力属性情報
483                         const OutmapInfo* outmapInfo =
484                             reinterpret_cast< const OutmapInfo* >(
485                                 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset );
486                         // マージしない場合はコピー.
487                         for( int i = 0; i < exe_info->outMapCount; ++i )
488                         {
489                             outmap_buffer[ i ] = outmapInfo[ i ];
490                         }
491                         outMapBufferCount = exe_info->outMapCount;
492                     }
493 
494                     for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index )
495                     {
496                         attr[ index ] = 0x1f1f1f1f;
497                         for ( int i = 0; i <outMapBufferCount; ++i )
498                         {
499                             bit32 c = 0;
500                             for ( int j = 0; outmap_buffer[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j )
501                             {
502                                 if ( ( outmap_buffer[ i ].mask & ( 1 << j ) ) == 0 ) continue;
503 
504                                 int value = 0x1f;
505                                 switch ( outmap_buffer[ i ].type )
506                                 {
507                                 case 0  :            value = 0x00 + c++; if (c == 2) clock |= 1 <<  0; break; // position
508                                 case 1  :            value = 0x04 + c++;             clock |= 1 << 24; break; // quaternion
509                                 case 2  :            value = 0x08 + c++;             clock |= 1 <<  1; break; // color
510                                 case 3  : if (c < 2) value = 0x0c + c++; useTex = 1; clock |= 1 <<  8; break; // texcoord0
511                                 case 4  :            value = 0x10;       useTex = 1; clock |= 3 << 16; break; // texcoord0w
512                                 case 5  : if (c < 2) value = 0x0e + c++; useTex = 1; clock |= 1 <<  9; break; // texcoord1
513                                 case 6  : if (c < 2) value = 0x16 + c++; useTex = 1; clock |= 1 << 10; break; // texcoord2
514                                 case 8  : if (c < 3) value = 0x12 + c++;             clock |= 1 << 24; break; // view
515                                 }
516                                 attr[ index ] = attr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 );
517                             }
518                         }
519                         if ( attr[ index ] != 0x1f1f1f1f )
520                         {
521                             outMask |= ( 1 << index );
522                             ++outNum;
523                         }
524                     }
525                 }
526 
527                 if ( IsEnableGeoShader() )
528                 {
529                     // 頂点シェーダーの出力属性の設定をもとめる
530                     m_DrawMode = PICA_DATA_DRAW_GEOMETRY_PRIMITIVE;
531 
532                     u32 vtxOutNum = 0;
533                     bit32 vtxOutMask = 0;
534                     bit32 vtxAttr[ VS_OUT_ATTR_INDEX_MAX ];
535 
536                     // プログラム情報
537                     const ExeImageInfo* exe_info = m_ExeImageInfo[ m_VtxShaderIndex ];
538                     const OutmapInfo* outmapInfo =
539                         reinterpret_cast< const OutmapInfo* >(
540                             reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset );
541 
542                     for ( int index = 0; index < VS_OUT_ATTR_INDEX_MAX; ++index )
543                     {
544                         vtxAttr[ index ] = 0x1f1f1f1f;
545                         for ( int i = 0; i < exe_info->outMapCount; ++i )
546                         {
547                             u32 c = 0;
548                             for ( int j = 0; outmapInfo[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j )
549                             {
550                                 if ( ( outmapInfo[ i ].mask & ( 1 << j ) ) == 0 ) continue;
551 
552                                 int value = 0x1f;
553                                 switch ( outmapInfo[ i ].type )
554                                 {
555                                 case 0  :            value = 0x00 + c++; break; // position
556                                 case 1  :            value = 0x04 + c++; break; // quaternion
557                                 case 2  :            value = 0x08 + c++; break; // color
558                                 case 3  : if (c < 2) value = 0x0c + c++; break; // texcoord0
559                                 case 4  :            value = 0x10;       break; // texcoord0w
560                                 case 5  : if (c < 2) value = 0x0e + c++; break; // texcoord1
561                                 case 6  : if (c < 2) value = 0x16 + c++; break; // texcoord2
562                                 case 8  : if (c < 3) value = 0x12 + c++; break; // view
563                                 case 9  : value = 0xff;
564                                 }
565                                 vtxAttr[ index ] = vtxAttr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 );
566                             }
567                         }
568                         if ( vtxAttr[ index ] != 0x1f1f1f1f )
569                         {
570                             vtxOutMask |= ( 1 << index );
571                             ++vtxOutNum;
572                         }
573                     }
574 
575                     bit32 gsDataMode = m_ExeImageInfo[ m_GeoShaderIndex ]->gsDataMode;
576 
577                     // GL_GEOMETRY_PRIMITIVE_DMP
578 
579                     // 0x229 [31:31],
580                     // データモード 1 の場合
581                     if ( gsDataMode == 1 )
582                     {
583                         *command++ = 0x80000000;
584                     }
585                     // データモード 0 と データモード2 の場合
586                     else
587                     {
588                         *command++ = 0x00000000;
589                     }
590                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa );
591 
592                     // 0x253
593                     *command++ = 0x00000000;
594                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 );
595 
596                     // 0x289 頂点シェーダーの出力数
597                     *command++ = 0x08000000 | (gsDataMode == 0 ? 0x0000 : 0x0100) | vtxOutNum - 1;
598                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb );
599 
600                     // 0x28a ジオメトリシェーダーのmainラベルのアドレス
601                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_GeoShaderIndex ]->mainAddress;
602                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_START_ADDR );
603 
604                     // 0x28d 頂点シェーダーの出力mask
605                     *command++ = outMask;
606                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_OUT_REG_MASK );
607 
608                     // 0x2ba 頂点シェーダーのmainラベルのアドレス
609                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress;
610                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR );
611 
612                     // 0x2bd 頂点シェーダーの出力レジスタマスク
613                     *command++ = vtxOutMask;
614                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK );
615 
616                     // 0x251 頂点シェーダーの出力数
617                     *command++ = vtxOutNum - 1;
618                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 );
619 
620                     // 0x28b 頂点シェーダーの出力とジオメトリシェーダーの入力は一致させているのが前提
621                     *command++ = 0x76543210;
622                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP0 ); // 0x28b
623 
624                     // 0x28c
625                     *command++ = 0xfedcba98;
626                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP1 );
627 
628                     // 0x254
629                     if ( ( gsDataMode == 1 ) && ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum != 0 ) )
630                     {
631                         *command++ = m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1;
632                         *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_MISC_REG1, 0x1 );
633                     }
634 
635                     // 0x252 用の値
636                     if ( gsDataMode == 2 )
637                     {
638                         gsDataMode |= 0x01                                                       << 24;
639                         gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexStartIndex ) << 16;
640                         gsDataMode |= ( vtxOutNum - 1 )                                          << 12;
641                         gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1 )    <<  8;
642                     }
643 
644                     // 0x252 データモードの指定
645                     *command++ = gsDataMode;
646                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 );
647 
648                     // 0x24a
649                     *command++ = vtxOutNum - 1;
650                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 );
651                 }
652                 else
653                 {
654                     // 0x229 [31:31]
655                     *command++ = 0x0;
656                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0x8 );
657 
658                     // 0x253 [0:0]
659                     *command++ = 0x0;
660                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x1 );
661 
662                     // 0x289 [31:24], [15:8], [3:0] 頂点シェーダーのモードの設定
663                     *command++ = 0xa0000000;
664                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb );
665 
666                     // 0x2ba 頂点シェーダーのmainラベルのアドレス
667                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress;
668                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR );
669 
670                     // 0x2bd 頂点シェーダーの出力レジスタマスク
671                     *command++ = outMask;
672                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK );
673 
674                     // 0x251
675                     *command++ = outNum - 1;
676                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 );
677 
678                     // 0x252
679                     *command++ = 0;
680                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 );
681 
682                     // 0x24a
683                     *command++ = outNum - 1;
684                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 );
685                 }
686 
687                 {
688                     // 0x25e [3:0]
689                     *command++ = outNum - 1;
690                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 0x1 );
691 
692                     // 0x04f
693                     *command++ = outNum;
694                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM0 );
695 
696                     // 出力属性のコマンド
697                     outNum = 0;
698                     for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index )
699                     {
700                         if ( attr[ index ] != 0x1f1f1f1f )
701                         {
702                             *command++ = attr[ index ];
703                             *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + outNum );
704                             ++outNum;
705                         }
706                     }
707                     for ( int index = outNum; index < OUT_ATTR_INDEX_MAX; ++index )
708                     {
709                         *command++ = attr[ index ];
710                         *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + index );
711                     }
712                 }
713 
714                 // 0x064 テクスチャ座標を使うかどうかを設定
715                 *command++ = useTex;
716                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_MODE );
717 
718                 // 0x06f 出力属性のクロック制御を設定
719                 *command++ = clock;
720                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_CLK );
721 
722                 if ( IsEnableGeoShader() )
723                 {
724                     // 0x25e
725                     *command++ = 0;
726                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 8 );
727                 }
728 
729                 return command;
730             }
731 
732             //------------------------------------------------------------------------
733 
MakeLoadCommand_(bit32 * command,const bit32 load_reg,const bit32 * src_buffer_ptr,const u32 src_data_num) const734             bit32* Shader::MakeLoadCommand_( bit32* command,
735                                            const bit32  load_reg,
736                                            const bit32* src_buffer_ptr,
737                                            const u32  src_data_num ) const
738             {
739                 enum { WRITE_MAX = 128 };
740 
741                 u32 rest = src_data_num;
742 
743                 while ( true )
744                 {
745                     if ( rest <= WRITE_MAX )
746                     {
747                         *command++ = *src_buffer_ptr++;
748                         *command++ = PICA_CMD_HEADER_BURST( load_reg, rest );
749                         std::memcpy( command, src_buffer_ptr, ( rest - 1 ) * sizeof( bit32 ) );
750                         command += rest - 1;
751 
752                         if ( ( rest & 1 ) == 0 ) *command++ = PADDING_DATA; // padding
753                         break;
754                     }
755                     else
756                     {
757                         *command++ = *src_buffer_ptr++;
758                         *command++ = PICA_CMD_HEADER_BURST( load_reg, WRITE_MAX );
759                         std::memcpy( command, src_buffer_ptr, ( WRITE_MAX - 1 ) * sizeof( bit32 ) );
760 
761                         command += WRITE_MAX - 1;
762                         src_buffer_ptr += WRITE_MAX - 1;
763 
764                         rest -= WRITE_MAX;
765                         if ( ( WRITE_MAX & 1 ) == 0 ) *command++ = PADDING_DATA; // padding
766                     }
767                 }
768 
769                 return command;
770             }
771 
772             //------------------------------------------------------------------------
773 
MakeDummyCommand_(bit32 * command,const bit32 load_reg,const u32 dataNum)774             bit32* Shader::MakeDummyCommand_( bit32* command,
775                                               const bit32 load_reg,
776                                               const u32 dataNum )
777             {
778                 *command++ = 0;
779                 *command++ = PICA_CMD_HEADER_BURST_BE( load_reg, dataNum, 0 );
780 
781                 for ( int i = 0; i < dataNum - ( dataNum & 1 ); ++i)
782                 {
783                     *command++ = PADDING_DATA;
784                 }
785 
786                 return command;
787             }
788 
789             //------------------------------------------------------------------------
790 
SearchBindSymbol(BindSymbol * symbol,const char * name) const791             bool Shader::SearchBindSymbol( BindSymbol* symbol,
792                                            const char* name ) const
793             {
794                 const int shader_index = ( symbol->shaderType == BindSymbol::SHADER_TYPE_GEOMETRY )
795                     ? GetGeoShaderIndex() : GetVtxShaderIndex();
796 
797                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
798 
799                 // プログラム情報
800                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
801 
802                 // シンボル情報
803                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
804                 const BindSymbolInfo* bind_symbol_info =
805                     reinterpret_cast< const BindSymbolInfo* >(
806                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
807 
808                 // 文字列情報
809                 const char* string =
810                     reinterpret_cast< const char* >(
811                         reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset );
812 
813                 // 検索
814                 u32 namelen = std::strlen( name );
815                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
816                 {
817                     const BindSymbolInfo& info = bind_symbol_info[ i ];
818 
819                     if ( std::strncmp( name, &string[ info.nameIndex ], namelen ) != 0 ) continue;
820                     if ( string[ info.nameIndex + namelen ] != '\0' &&  string[ info.nameIndex + namelen ] != '.' ) continue;
821 
822                     symbol->name  = &string[ info.nameIndex ];
823                     symbol->start = (info.regIndex & 0x0000ffff);
824                     symbol->end   = (info.regIndex & 0xffff0000) >> 16;
825 
826                     if ( 136 <= symbol->start )
827                     {
828                         return false;
829                     }
830                     else if ( 120 <= symbol->start )
831                     {
832                         symbol->start -= 120;
833                         symbol->end   -= 120;
834 
835                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL;
836                     }
837                     else if ( 112 <= symbol->start )
838                     {
839                         symbol->start -= 112;
840                         symbol->end   -= 112;
841 
842                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER;
843                     }
844                     else if ( 16 <= symbol->start )
845                     {
846                         symbol->start -= 16;
847                         symbol->end   -= 16;
848 
849                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT;
850                     }
851                     else
852                     {
853                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT;
854                     }
855                 }
856 
857                 return false;
858             }
859 
860             //------------------------------------------------------------------------
861 
SearchBindSymbolNum(const BindSymbol::ShaderType shader_type,const BindSymbol::SymbolType symbol_type) const862             u32 Shader::SearchBindSymbolNum(
863                 const BindSymbol::ShaderType shader_type,
864                 const BindSymbol::SymbolType symbol_type ) const
865             {
866                 const int shader_index = ( shader_type == BindSymbol::SHADER_TYPE_GEOMETRY ) ? GetGeoShaderIndex() : GetVtxShaderIndex();
867                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
868 
869                 // プログラム情報
870                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
871 
872                 // 出力属性情報
873                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
874                 const BindSymbolInfo* bind_symbol_info =
875                     reinterpret_cast< const BindSymbolInfo* >(
876                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
877 
878                 int num = 0;
879 
880                 // 検索
881                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
882                 {
883                     int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff;
884 
885                     if ( 120 <= regStart && regStart < 136 &&
886                          symbol_type == BindSymbol::SYMBOL_TYPE_BOOL )
887                     {
888                         ++num;
889                     }
890                     else if ( 112 <= regStart && regStart < 115 &&
891                               symbol_type == BindSymbol::SYMBOL_TYPE_INTEGER )
892                     {
893                         ++num;
894                     }
895                     else if ( 16 <= regStart && regStart < 111 &&
896                               symbol_type == BindSymbol::SYMBOL_TYPE_FLOAT )
897                     {
898                         ++num;
899                     }
900                     else if ( regStart <  15 &&
901                               symbol_type == BindSymbol::SYMBOL_TYPE_INPUT )
902                     {
903                         ++num;
904                     }
905                 }
906 
907                 return num;
908             }
909 
910             //------------------------------------------------------------------------
911 
SearchBindSymbol(BindSymbol * symbol,const u8 symbol_index) const912             bool Shader::SearchBindSymbol(
913                 BindSymbol* symbol,
914                 const u8 symbol_index ) const
915             {
916                 const BindSymbol::ShaderType shaderType = symbol->shaderType;
917 
918                 const int shader_index = ( shaderType == BindSymbol::SHADER_TYPE_GEOMETRY )
919                     ? GetGeoShaderIndex() : GetVtxShaderIndex();
920 
921                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
922 
923                 // プログラム情報
924                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
925 
926                 // シンボル情報
927                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
928                 const BindSymbolInfo* bind_symbol_info =
929                     reinterpret_cast< const BindSymbolInfo* >(
930                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
931 
932                 // 文字列情報
933                 const char* string =
934                     reinterpret_cast< const char* >(
935                         reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset );
936 
937                 int index = -1;
938 
939                 // 検索
940                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
941                 {
942                     int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff;
943 
944                     // Bool registers
945                     if ( 120 <= regStart && regStart < 136 )
946                     {
947                         ++index;
948                     }
949                     // Integer registers
950                     else if ( 112 <= regStart && regStart < 115 )
951                     {
952                         ++index;
953                     }
954                     // Constant registers
955                     else if ( 16 <= regStart && regStart < 111 )
956                     {
957                         ++index;
958                     }
959                     // Input registers
960                     else if ( regStart <  15 )
961                     {
962                         ++index;
963                     }
964                     else
965                     {
966                         return false;
967                     }
968 
969                     if ( index == symbol_index )
970                     {
971                         const BindSymbolInfo& info = bind_symbol_info[ i ];
972 
973                         symbol->name  = &string[ info.nameIndex ];
974                         symbol->start = (info.regIndex & 0x0000ffff);
975                         symbol->end   = (info.regIndex & 0xffff0000) >> 16;
976 
977                         if ( 120 <= symbol->start )
978                         {
979                             symbol->start -= 120;
980                             symbol->end   -= 120;
981 
982                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL;
983                         }
984                         else if ( 112 <= symbol->start )
985                         {
986                             symbol->start -= 112;
987                             symbol->end -= 112;
988 
989                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER;
990                         }
991                         else if (  16 <= symbol->start )
992                         {
993                             symbol->start -=  16;
994                             symbol->end -=  16;
995 
996                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT;
997                         }
998                         else
999                         {
1000                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT;
1001                         }
1002                     }
1003                 }
1004 
1005                 return false;
1006             }
1007 
1008         } //namespace CTR
1009     } //namespace gr
1010 } //namespace nn
1011