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