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: 26006 $
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 u32* binary = reinterpret_cast< const u32* >( 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 u32* package_info = binary;
50                 NN_GR_ASSERT( *binary == 0x504C5644 ); // DVLP
51                 ++binary;
52                 ++binary;
53 
54                 m_Instruction = reinterpret_cast< const u32* >( (u8*)package_info + *binary );
55                 ++binary;
56 
57                 m_InstructionCount = *binary;
58                 ++binary;
59 
60                 const u32* swizzle = reinterpret_cast< const u32* >( (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(u32 * command) const104             u32* Shader::MakeFullCommand( u32* 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(u32 * command) const134             u32* Shader::MakePrepareCommand( u32* 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(u32 * command) const176             u32* Shader::MakeVtxProgramCommand( u32* command ) const
177             {
178                 int shader_index = GetVtxShaderIndex();
179                 u32 reg_addr     = PICA_REG_VS_PROG_ADDR;        // 0x2cb
180                 u32 reg_load     = PICA_REG_VS_PROG_DATA0;       // 0x2cc
181                 u32 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(u32 * command) const216             u32* Shader::MakeGeoProgramCommand( u32* command ) const
217             {
218                 int shader_index = GetGeoShaderIndex();
219                 u32 reg_addr     = PICA_REG_GS_PROG_ADDR;        // 0x29b
220                 u32 reg_load     = PICA_REG_GS_PROG_DATA0;       // 0x29c
221                 u32 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_(u32 * command,const bool is_geometry_shader)250             u32* Shader::MakeConstRgCommand_( u32* command,
251                                               const bool is_geometry_shader )
252             {
253                 int  shader_index = GetVtxShaderIndex();
254                 u32  reg_float    = PICA_REG_VS_FLOAT_ADDR; // 0x2c0
255                 u32  reg_integer  = PICA_REG_VS_INT0;       // 0x2b1
256                 u32* 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; u32 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 u32* 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_(u32 * command)310             u32* Shader::MakeOutAttrCommand_( u32* 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                 u32 useTex  = 0;
331                 u32 clock   = 0;
332                 u32 outMask = 0;
333                 u32 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                         u32 gs_copy_mask = 0;
349                         u32 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                             u32 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                     u32 vtxOutMask = 0;
459                     u32 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                     u32 gsDataMode = m_ExeImageInfo[ m_GeoShaderIndex ]->gsDataMode;
501 
502                     // GL_GEOMETRY_PRIMITIVE_DMP
503                     *command++ = 0x00000000;
504                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa );      // 0x229
505 
506                     // GL_GEOMETRY_PRIMITIVE_DMP
507                     *command++ = 0x00000000;
508                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 );      // 0x253
509 
510                     // 頂点シェーダーの出力数
511                     *command++ = 0x08000000 | (gsDataMode == 0 ? 0x0000 : 0x0100) | vtxOutNum - 1;
512                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb );     // 0x289
513 
514                     // ジオメトリシェーダーのmainラベルのアドレス
515                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_GeoShaderIndex ]->mainAddress;
516                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_START_ADDR );           // 0x28a
517 
518                     // 頂点シェーダーの出力mask
519                     *command++ = outMask;
520                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_OUT_REG_MASK );         // 0x28d
521 
522                     // 頂点シェーダーのmainラベルのアドレス
523                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress;
524                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR );           // 0x2ba
525 
526                     // 頂点シェーダーの出力レジスタマスク
527                     *command++ = vtxOutMask;
528                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK );         // 0x2bd
529 
530                     // 頂点シェーダーの出力数
531                     *command++ = vtxOutNum - 1;
532                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 );         // 0x251
533 
534                     // 頂点シェーダーの出力とジオメトリシェーダーの入力は一致させているのが前提
535                     *command++ = 0x76543210;
536                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP0 );     // 0x28b
537                     *command++ = 0xfedcba98;
538                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP1 );     // 0x28c
539 
540                     if ( gsDataMode == 2 )
541                     {
542                         gsDataMode |= 0x01                                                     << 24;
543                         gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexStartIndex ) << 16;
544                         gsDataMode |= ( vtxOutNum - 1 )                                        << 12;
545                         gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1 )    <<  8;
546                     }
547                     *command++ = gsDataMode;
548                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 );            // 0x252
549 
550                     *command++ = vtxOutNum - 1;
551                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 );         // 0x24a
552                 }
553                 else
554                 {
555                     *command++ = 0x00000100;
556                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa );      // 0x229
557 
558                     *command++ = 0x00000100;
559                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 );      // 0x253
560 
561                     // 頂点シェーダーのmainラベルのアドレス
562                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress;
563                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR );           // 0x2ba
564 
565                     // 頂点シェーダーの出力レジスタマスク
566                     *command++ = outMask;
567                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK );         // 0x2bd
568 
569                     *command++ = outNum - 1;
570                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 );         // 0x251
571 
572                     *command++ = 0;
573                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 );            // 0x252
574 
575                     *command++ = outNum - 1;
576                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 );         // 0x24a
577                 }
578 
579                 {
580                     *command++ = outNum - 1;
581                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 1 );   // 0x25e
582 
583                     *command++ = outNum;
584                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM0 );         // 0x04f
585 
586                     // 出力属性のコマンド
587                     outNum = 0;
588                     for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index )
589                     {
590                         if ( attr[ index ] != 0x1f1f1f1f )
591                         {
592                             *command++ = attr[ index ];
593                             *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + outNum );
594                             ++outNum;
595                         }
596                     }
597                     for ( int index = outNum; index < OUT_ATTR_INDEX_MAX; ++index )
598                     {
599                         *command++ = attr[ index ];
600                         *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + index );
601                     }
602                 }
603 
604                 // テクスチャ座標を使うかどうかを設定
605                 *command++ = useTex;
606                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_MODE );           // 0x064
607 
608                 // 出力属性のクロック制御を設定
609                 *command++ = clock;
610                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_CLK );            // 0x06f
611 
612                 if ( IsEnableGeoShader() )
613                 {
614                     *command++ = 0;
615                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 8 );  // 0x25e
616                 }
617 
618                 return command;
619             }
620 
621             //------------------------------------------------------------------------
622 
MakeLoadCommand_(u32 * command,const u32 load_reg,const u32 * src_buffer_ptr,const u32 src_data_num) const623             u32* Shader::MakeLoadCommand_( u32* command,
624                                            const u32  load_reg,
625                                            const u32* src_buffer_ptr,
626                                            const u32  src_data_num ) const
627             {
628                 enum { WRITE_MAX = 128 };
629 
630                 u32 rest = src_data_num;
631 
632                 while ( true )
633                 {
634                     if ( rest <= WRITE_MAX )
635                     {
636                         *command++ = *src_buffer_ptr++;
637                         *command++ = PICA_CMD_HEADER_BURST( load_reg, rest );
638                         std::memcpy( command, src_buffer_ptr, ( rest - 1 ) * sizeof( u32 ) );
639                         command += rest - 1;
640 
641                         if ( ( rest & 1 ) == 0 ) *command++ = PADDING_DATA; // padding
642                         break;
643                     }
644                     else
645                     {
646                         *command++ = *src_buffer_ptr++;
647                         *command++ = PICA_CMD_HEADER_BURST( load_reg, WRITE_MAX );
648                         std::memcpy( command, src_buffer_ptr, ( WRITE_MAX - 1 ) * sizeof( u32 ) );
649 
650                         command += WRITE_MAX - 1;
651                         src_buffer_ptr += WRITE_MAX - 1;
652 
653                         rest -= WRITE_MAX;
654                         if ( ( WRITE_MAX & 1 ) == 0 ) *command++ = PADDING_DATA; // padding
655                     }
656                 }
657 
658                 return command;
659             }
660 
661             //------------------------------------------------------------------------
662 
MakeDummyCommand_(u32 * command,const u32 load_reg,const u32 dataNum) const663             u32* Shader::MakeDummyCommand_( u32* command,
664                                             const u32 load_reg,
665                                             const u32 dataNum ) const
666             {
667                 *command++ = 0;
668                 *command++ = PICA_CMD_HEADER_BURST_BE( load_reg, dataNum, 0 );
669 
670                 for ( int i = 0; i < dataNum - ( dataNum & 1 ); ++i)
671                 {
672                     *command++ = PADDING_DATA;
673                 }
674 
675                 return command;
676             }
677 
678             //------------------------------------------------------------------------
679 
SearchBindSymbol(BindSymbol * symbol,const char * name) const680             bool Shader::SearchBindSymbol( BindSymbol* symbol,
681                                            const char* name ) const
682             {
683                 const int shader_index = symbol->shaderType == BindSymbol::SHADER_TYPE_GEOMETRY ? GetGeoShaderIndex() : GetVtxShaderIndex();
684                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
685 
686                 // プログラム情報
687                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
688 
689                 // シンボル情報
690                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
691                 const BindSymbolInfo* bind_symbol_info =
692                     reinterpret_cast< const BindSymbolInfo* >(
693                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
694 
695                 // 文字列情報
696                 const char* string =
697                     reinterpret_cast< const char* >(
698                         reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset );
699 
700                 // 検索
701                 u32 namelen = std::strlen( name );
702                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
703                 {
704                     const BindSymbolInfo& info = bind_symbol_info[ i ];
705 
706                     if ( std::strncmp( name, &string[ info.nameIndex ], namelen ) != 0 ) continue;
707                     if ( string[ info.nameIndex + namelen ] != '\0' &&  string[ info.nameIndex + namelen ] != '.' ) continue;
708 
709                     symbol->name  = &string[ info.nameIndex ];
710                     symbol->start = (info.regIndex & 0x0000ffff);
711                     symbol->end   = (info.regIndex & 0xffff0000) >> 16;
712 
713                     if ( 136 <= symbol->start )
714                     {
715                         return false;
716                     }
717                     else if ( 120 <= symbol->start )
718                     {
719                         symbol->start -= 120;
720                         symbol->end   -= 120;
721                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL;
722                     }
723                     else if ( 112 <= symbol->start )
724                     {
725                         symbol->start -= 112;
726                         symbol->end   -= 112;
727                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER;
728                     }
729                     else if ( 16 <= symbol->start )
730                     {
731                         symbol->start -= 16;
732                         symbol->end   -= 16;
733                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT;
734                     }
735                     else
736                     {
737                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT;
738                     }
739                 }
740 
741                 return false;
742             }
743 
744             //------------------------------------------------------------------------
745 
SearchBindSymbolNum(const BindSymbol::ShaderType shader_type,const BindSymbol::SymbolType symbol_type) const746             u32 Shader::SearchBindSymbolNum(
747                 const BindSymbol::ShaderType shader_type,
748                 const BindSymbol::SymbolType symbol_type ) const
749             {
750                 const int shader_index = ( shader_type == BindSymbol::SHADER_TYPE_GEOMETRY ) ? GetGeoShaderIndex() : GetVtxShaderIndex();
751                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
752 
753                 // プログラム情報
754                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
755 
756                 // 出力属性情報
757                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
758                 const BindSymbolInfo* bind_symbol_info =
759                     reinterpret_cast< const BindSymbolInfo* >(
760                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
761 
762                 int num = 0;
763 
764                 // 検索
765                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
766                 {
767                     int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff;
768 
769                     if      ( 120 <= regStart && regStart < 136 && symbol_type == BindSymbol::SYMBOL_TYPE_BOOL    ) ++num;
770                     else if ( 112 <= regStart && regStart < 115 && symbol_type == BindSymbol::SYMBOL_TYPE_INTEGER ) ++num;
771                     else if (  16 <= regStart && regStart < 111 && symbol_type == BindSymbol::SYMBOL_TYPE_FLOAT   ) ++num;
772                     else if (                    regStart <  15 && symbol_type == BindSymbol::SYMBOL_TYPE_INPUT   ) ++num;
773                 }
774 
775                 return num;
776             }
777 
778             //------------------------------------------------------------------------
779 
SearchBindSymbol(BindSymbol * symbol,const u8 symbol_index) const780             bool Shader::SearchBindSymbol(
781                 BindSymbol* symbol,
782                 const u8 symbol_index ) const
783             {
784                 const BindSymbol::SymbolType type = symbol->symbolType;
785 
786                 const int shader_index = type == ( BindSymbol::SHADER_TYPE_GEOMETRY )  ? GetGeoShaderIndex() : GetVtxShaderIndex();
787                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
788 
789                 // プログラム情報
790                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
791 
792                 // シンボル情報
793                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
794                 const BindSymbolInfo* bind_symbol_info =
795                     reinterpret_cast< const BindSymbolInfo* >(
796                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
797 
798                 // 文字列情報
799                 const char* string =
800                     reinterpret_cast< const char* >(
801                         reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset );
802 
803                 int index = -1;
804 
805                 // 検索
806                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
807                 {
808                     int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff;
809 
810                     if      ( 120 <= regStart && regStart < 136 && type == BindSymbol::SYMBOL_TYPE_BOOL    ) ++index;
811                     else if ( 112 <= regStart && regStart < 115 && type == BindSymbol::SYMBOL_TYPE_INTEGER ) ++index;
812                     else if (  16 <= regStart && regStart < 111 && type == BindSymbol::SYMBOL_TYPE_FLOAT   ) ++index;
813                     else if (                    regStart <  15 && type == BindSymbol::SYMBOL_TYPE_INPUT   ) ++index;
814 
815                     if ( index == symbol_index )
816                     {
817                         const BindSymbolInfo& info = bind_symbol_info[ i ];
818                         symbol->name  = &string[ info.nameIndex ];
819                         symbol->start = (info.regIndex & 0x0000ffff);
820                         symbol->end   = (info.regIndex & 0xffff0000) >> 16;
821 
822                         if      ( 120 <= symbol->start ) { symbol->start -= 120; symbol->end -= 120; }
823                         else if ( 112 <= symbol->start ) { symbol->start -= 112; symbol->end -= 112; }
824                         else if (  16 <= symbol->start ) { symbol->start -=  16; symbol->end -=  16; }
825                         return true;
826                     }
827                 }
828 
829                 return false;
830             }
831 
832         } //namespace CTR
833     } //namespace gr
834 } //namespace nn
835