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: 33699 $
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                         // 最初にVSとGS両方で指定されているものを設定.
417                         NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX );
418                         for( int g = 0; g < exe_info->outMapCount; ++g )
419                         {
420                             for( int v = 0; v < vtx_exe_info->outMapCount; ++v )
421                             {
422                                 if ( outmapInfo[ g ].type == vtxOutmapInfo[ v ].type )
423                                 {
424                                     NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_INDEX_MAX );
425                                     outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type;
426                                     outmap_buffer[ outMapBufferCount ].index = outMapBufferCount;
427                                     outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask;
428                                     gs_copy_mask |= 1 << g;
429                                     vs_copy_mask |= 1 << v;
430                                     ++outMapBufferCount;
431                                 }
432                             }
433                         }
434                         // 次にGSのみで定義されているものを設定.
435                         for( int g = 0; g < exe_info->outMapCount; ++g )
436                         {
437                             if ( !( gs_copy_mask & ( 1 << g ) ) && ( outmapInfo[ g ].type >= 0 && outmapInfo[ g ].type < 9 && outmapInfo[ g ].type != 7 ) )
438                             {
439                                 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX );
440                                 outmap_buffer[ outMapBufferCount ].type = outmapInfo[ g ].type;
441                                 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount;
442                                 outmap_buffer[ outMapBufferCount ].mask = outmapInfo[ g ].mask;
443                                 ++outMapBufferCount;
444                             }
445                         }
446                         // 最後ににVSのみで定義されているものを設定.
447                         for( int v = 0; v < vtx_exe_info->outMapCount; ++v )
448                         {
449                             if ( !( vs_copy_mask & ( 1 << v ) ) &&
450                                   ( vtxOutmapInfo[ v ].type >= 0 && vtxOutmapInfo[ v ].type < 9 && vtxOutmapInfo[ v ].type != 7 ) )
451                             {
452                                 NN_GR_ASSERT( outMapBufferCount < OUT_ATTR_BUFFER_MAX );
453                                 outmap_buffer[ outMapBufferCount ].type = vtxOutmapInfo[ v ].type;
454                                 outmap_buffer[ outMapBufferCount ].index = outMapBufferCount;
455                                 outmap_buffer[ outMapBufferCount ].mask = vtxOutmapInfo[ v ].mask;
456                                 ++outMapBufferCount;
457                             }
458                         }
459                     }
460                     else
461                     {
462                         // 出力属性情報
463                         const OutmapInfo* outmapInfo =
464                             reinterpret_cast< const OutmapInfo* >(
465                                 reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset );
466                         // マージしない場合はコピー.
467                         for( int i = 0; i < exe_info->outMapCount; ++i )
468                         {
469                             outmap_buffer[ i ] = outmapInfo[ i ];
470                         }
471                         outMapBufferCount = exe_info->outMapCount;
472                     }
473 
474                     for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index )
475                     {
476                         attr[ index ] = 0x1f1f1f1f;
477                         for ( int i = 0; i <outMapBufferCount; ++i )
478                         {
479                             bit32 c = 0;
480                             for ( int j = 0; outmap_buffer[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j )
481                             {
482                                 if ( ( outmap_buffer[ i ].mask & ( 1 << j ) ) == 0 ) continue;
483 
484                                 int value = 0x1f;
485                                 switch ( outmap_buffer[ i ].type )
486                                 {
487                                 case 0  :            value = 0x00 + c++; if (c == 2) clock |= 1 <<  0; break; // position
488                                 case 1  :            value = 0x04 + c++;             clock |= 1 << 24; break; // quaternion
489                                 case 2  :            value = 0x08 + c++;             clock |= 1 <<  1; break; // color
490                                 case 3  : if (c < 2) value = 0x0c + c++; useTex = 1; clock |= 1 <<  8; break; // texcoord0
491                                 case 4  :            value = 0x10;       useTex = 1; clock |= 3 << 16; break; // texcoord0w
492                                 case 5  : if (c < 2) value = 0x0e + c++; useTex = 1; clock |= 1 <<  9; break; // texcoord1
493                                 case 6  : if (c < 2) value = 0x16 + c++; useTex = 1; clock |= 1 << 10; break; // texcoord2
494                                 case 8  : if (c < 3) value = 0x12 + c++;             clock |= 1 << 24; break; // view
495                                 }
496                                 attr[ index ] = attr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 );
497                             }
498                         }
499                         if ( attr[ index ] != 0x1f1f1f1f )
500                         {
501                             outMask |= ( 1 << index );
502                             ++outNum;
503                         }
504                     }
505                 }
506 
507                 if ( IsEnableGeoShader() )
508                 {
509                     // 頂点シェーダーの出力属性の設定をもとめる
510                     m_DrawMode = PICA_DATA_DRAW_GEOMETRY_PRIMITIVE;
511 
512                     u32 vtxOutNum = 0;
513                     bit32 vtxOutMask = 0;
514                     bit32 vtxAttr[ VS_OUT_ATTR_INDEX_MAX ];
515 
516                     // プログラム情報
517                     const ExeImageInfo* exe_info = m_ExeImageInfo[ m_VtxShaderIndex ];
518                     const OutmapInfo* outmapInfo =
519                         reinterpret_cast< const OutmapInfo* >(
520                             reinterpret_cast< const u8* >( exe_info ) + exe_info->outMapOffset );
521 
522                     for ( int index = 0; index < VS_OUT_ATTR_INDEX_MAX; ++index )
523                     {
524                         vtxAttr[ index ] = 0x1f1f1f1f;
525                         for ( int i = 0; i < exe_info->outMapCount; ++i )
526                         {
527                             u32 c = 0;
528                             for ( int j = 0; outmapInfo[ i ].index == index && j < OUT_ATTR_DIMENTION_MAX; ++j )
529                             {
530                                 if ( ( outmapInfo[ i ].mask & ( 1 << j ) ) == 0 ) continue;
531 
532                                 int value = 0x1f;
533                                 switch ( outmapInfo[ i ].type )
534                                 {
535                                 case 0  :            value = 0x00 + c++; break; // position
536                                 case 1  :            value = 0x04 + c++; break; // quaternion
537                                 case 2  :            value = 0x08 + c++; break; // color
538                                 case 3  : if (c < 2) value = 0x0c + c++; break; // texcoord0
539                                 case 4  :            value = 0x10;       break; // texcoord0w
540                                 case 5  : if (c < 2) value = 0x0e + c++; break; // texcoord1
541                                 case 6  : if (c < 2) value = 0x16 + c++; break; // texcoord2
542                                 case 8  : if (c < 3) value = 0x12 + c++; break; // view
543                                 case 9  : value = 0xff;
544                                 }
545                                 vtxAttr[ index ] = vtxAttr[ index ] & ~( 0xff << ( j * 8 ) ) | value << ( j * 8 );
546                             }
547                         }
548                         if ( vtxAttr[ index ] != 0x1f1f1f1f )
549                         {
550                             vtxOutMask |= ( 1 << index );
551                             ++vtxOutNum;
552                         }
553                     }
554 
555                     bit32 gsDataMode = m_ExeImageInfo[ m_GeoShaderIndex ]->gsDataMode;
556 
557                     // GL_GEOMETRY_PRIMITIVE_DMP
558 
559                     // 0x229 [31:31],
560                     // データモード 1 の場合
561                     if ( gsDataMode == 1 )
562                     {
563                         *command++ = 0x80000000;
564                     }
565                     // データモード 0 と データモード2 の場合
566                     else
567                     {
568                         *command++ = 0x00000000;
569                     }
570                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0xa );
571 
572                     // 0x253
573                     *command++ = 0x00000000;
574                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x3 );
575 
576                     // 0x289 頂点シェーダーの出力数
577                     *command++ = 0x08000000 | (gsDataMode == 0 ? 0x0000 : 0x0100) | vtxOutNum - 1;
578                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb );
579 
580                     // 0x28a ジオメトリシェーダーのmainラベルのアドレス
581                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_GeoShaderIndex ]->mainAddress;
582                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_START_ADDR );
583 
584                     // 0x28d 頂点シェーダーの出力mask
585                     *command++ = outMask;
586                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_OUT_REG_MASK );
587 
588                     // 0x2ba 頂点シェーダーのmainラベルのアドレス
589                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress;
590                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR );
591 
592                     // 0x2bd 頂点シェーダーの出力レジスタマスク
593                     *command++ = vtxOutMask;
594                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK );
595 
596                     // 0x251 頂点シェーダーの出力数
597                     *command++ = vtxOutNum - 1;
598                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 );
599 
600                     // 0x28b 頂点シェーダーの出力とジオメトリシェーダーの入力は一致させているのが前提
601                     *command++ = 0x76543210;
602                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP0 ); // 0x28b
603 
604                     // 0x28c
605                     *command++ = 0xfedcba98;
606                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_ATTR_IN_REG_MAP1 );
607 
608                     // 0x254
609                     if ( ( gsDataMode == 1 ) && ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum != 0 ) )
610                     {
611                         *command++ = m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1;
612                         *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_MISC_REG1, 0x1 );
613                     }
614 
615                     // 0x252 用の値
616                     if ( gsDataMode == 2 )
617                     {
618                         gsDataMode |= 0x01                                                       << 24;
619                         gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexStartIndex ) << 16;
620                         gsDataMode |= ( vtxOutNum - 1 )                                          << 12;
621                         gsDataMode |= ( m_ExeImageInfo[ m_GeoShaderIndex ]->gsVertexNum - 1 )    <<  8;
622                     }
623 
624                     // 0x252 データモードの指定
625                     *command++ = gsDataMode;
626                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 );
627 
628                     // 0x24a
629                     *command++ = vtxOutNum - 1;
630                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 );
631                 }
632                 else
633                 {
634                     // 0x229 [31:31]
635                     *command++ = 0x0;
636                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0x8 );
637 
638                     // 0x253 [0:0]
639                     *command++ = 0x0;
640                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x1 );
641 
642                     // 0x289 [31:24], [15:8], [3:0] 頂点シェーダーのモードの設定
643                     *command++ = 0xa0000000;
644                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GS_ATTR_NUM, 0xb );
645 
646                     // 0x2ba 頂点シェーダーのmainラベルのアドレス
647                     *command++ = 0x7fff0000 | m_ExeImageInfo[ m_VtxShaderIndex ]->mainAddress;
648                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR );
649 
650                     // 0x2bd 頂点シェーダーの出力レジスタマスク
651                     *command++ = outMask;
652                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK );
653 
654                     // 0x251
655                     *command++ = outNum - 1;
656                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 );
657 
658                     // 0x252
659                     *command++ = 0;
660                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 );
661 
662                     // 0x24a
663                     *command++ = outNum - 1;
664                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 );
665                 }
666 
667                 {
668                     // 0x25e [3:0]
669                     *command++ = outNum - 1;
670                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 0x1 );
671 
672                     // 0x04f
673                     *command++ = outNum;
674                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM0 );
675 
676                     // 出力属性のコマンド
677                     outNum = 0;
678                     for ( int index = 0; index < OUT_ATTR_INDEX_MAX; ++index )
679                     {
680                         if ( attr[ index ] != 0x1f1f1f1f )
681                         {
682                             *command++ = attr[ index ];
683                             *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + outNum );
684                             ++outNum;
685                         }
686                     }
687                     for ( int index = outNum; index < OUT_ATTR_INDEX_MAX; ++index )
688                     {
689                         *command++ = attr[ index ];
690                         *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR0 + index );
691                     }
692                 }
693 
694                 // 0x064 テクスチャ座標を使うかどうかを設定
695                 *command++ = useTex;
696                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_MODE );
697 
698                 // 0x06f 出力属性のクロック制御を設定
699                 *command++ = clock;
700                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_CLK );
701 
702                 if ( IsEnableGeoShader() )
703                 {
704                     // 0x25e
705                     *command++ = 0;
706                     *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 8 );
707                 }
708 
709                 return command;
710             }
711 
712             //------------------------------------------------------------------------
713 
MakeLoadCommand_(bit32 * command,const bit32 load_reg,const bit32 * src_buffer_ptr,const u32 src_data_num) const714             bit32* Shader::MakeLoadCommand_( bit32* command,
715                                            const bit32  load_reg,
716                                            const bit32* src_buffer_ptr,
717                                            const u32  src_data_num ) const
718             {
719                 enum { WRITE_MAX = 128 };
720 
721                 u32 rest = src_data_num;
722 
723                 while ( true )
724                 {
725                     if ( rest <= WRITE_MAX )
726                     {
727                         *command++ = *src_buffer_ptr++;
728                         *command++ = PICA_CMD_HEADER_BURST( load_reg, rest );
729                         std::memcpy( command, src_buffer_ptr, ( rest - 1 ) * sizeof( bit32 ) );
730                         command += rest - 1;
731 
732                         if ( ( rest & 1 ) == 0 ) *command++ = PADDING_DATA; // padding
733                         break;
734                     }
735                     else
736                     {
737                         *command++ = *src_buffer_ptr++;
738                         *command++ = PICA_CMD_HEADER_BURST( load_reg, WRITE_MAX );
739                         std::memcpy( command, src_buffer_ptr, ( WRITE_MAX - 1 ) * sizeof( bit32 ) );
740 
741                         command += WRITE_MAX - 1;
742                         src_buffer_ptr += WRITE_MAX - 1;
743 
744                         rest -= WRITE_MAX;
745                         if ( ( WRITE_MAX & 1 ) == 0 ) *command++ = PADDING_DATA; // padding
746                     }
747                 }
748 
749                 return command;
750             }
751 
752             //------------------------------------------------------------------------
753 
MakeDummyCommand_(bit32 * command,const bit32 load_reg,const u32 dataNum)754             bit32* Shader::MakeDummyCommand_( bit32* command,
755                                               const bit32 load_reg,
756                                               const u32 dataNum )
757             {
758                 *command++ = 0;
759                 *command++ = PICA_CMD_HEADER_BURST_BE( load_reg, dataNum, 0 );
760 
761                 for ( int i = 0; i < dataNum - ( dataNum & 1 ); ++i)
762                 {
763                     *command++ = PADDING_DATA;
764                 }
765 
766                 return command;
767             }
768 
769             //------------------------------------------------------------------------
770 
SearchBindSymbol(BindSymbol * symbol,const char * name) const771             bool Shader::SearchBindSymbol( BindSymbol* symbol,
772                                            const char* name ) const
773             {
774                 const int shader_index = ( symbol->shaderType == BindSymbol::SHADER_TYPE_GEOMETRY )
775                     ? GetGeoShaderIndex() : GetVtxShaderIndex();
776 
777                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
778 
779                 // プログラム情報
780                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
781 
782                 // シンボル情報
783                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
784                 const BindSymbolInfo* bind_symbol_info =
785                     reinterpret_cast< const BindSymbolInfo* >(
786                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
787 
788                 // 文字列情報
789                 const char* string =
790                     reinterpret_cast< const char* >(
791                         reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset );
792 
793                 // 検索
794                 u32 namelen = std::strlen( name );
795                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
796                 {
797                     const BindSymbolInfo& info = bind_symbol_info[ i ];
798 
799                     if ( std::strncmp( name, &string[ info.nameIndex ], namelen ) != 0 ) continue;
800                     if ( string[ info.nameIndex + namelen ] != '\0' &&  string[ info.nameIndex + namelen ] != '.' ) continue;
801 
802                     symbol->name  = &string[ info.nameIndex ];
803                     symbol->start = (info.regIndex & 0x0000ffff);
804                     symbol->end   = (info.regIndex & 0xffff0000) >> 16;
805 
806                     if ( 136 <= symbol->start )
807                     {
808                         return false;
809                     }
810                     else if ( 120 <= symbol->start )
811                     {
812                         symbol->start -= 120;
813                         symbol->end   -= 120;
814 
815                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL;
816                     }
817                     else if ( 112 <= symbol->start )
818                     {
819                         symbol->start -= 112;
820                         symbol->end   -= 112;
821 
822                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER;
823                     }
824                     else if ( 16 <= symbol->start )
825                     {
826                         symbol->start -= 16;
827                         symbol->end   -= 16;
828 
829                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT;
830                     }
831                     else
832                     {
833                         return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT;
834                     }
835                 }
836 
837                 return false;
838             }
839 
840             //------------------------------------------------------------------------
841 
SearchBindSymbolNum(const BindSymbol::ShaderType shader_type,const BindSymbol::SymbolType symbol_type) const842             u32 Shader::SearchBindSymbolNum(
843                 const BindSymbol::ShaderType shader_type,
844                 const BindSymbol::SymbolType symbol_type ) const
845             {
846                 const int shader_index = ( shader_type == BindSymbol::SHADER_TYPE_GEOMETRY ) ? GetGeoShaderIndex() : GetVtxShaderIndex();
847                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
848 
849                 // プログラム情報
850                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
851 
852                 // 出力属性情報
853                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
854                 const BindSymbolInfo* bind_symbol_info =
855                     reinterpret_cast< const BindSymbolInfo* >(
856                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
857 
858                 int num = 0;
859 
860                 // 検索
861                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
862                 {
863                     int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff;
864 
865                     if ( 120 <= regStart && regStart < 136 &&
866                          symbol_type == BindSymbol::SYMBOL_TYPE_BOOL )
867                     {
868                         ++num;
869                     }
870                     else if ( 112 <= regStart && regStart < 115 &&
871                               symbol_type == BindSymbol::SYMBOL_TYPE_INTEGER )
872                     {
873                         ++num;
874                     }
875                     else if ( 16 <= regStart && regStart < 111 &&
876                               symbol_type == BindSymbol::SYMBOL_TYPE_FLOAT )
877                     {
878                         ++num;
879                     }
880                     else if ( regStart <  15 &&
881                               symbol_type == BindSymbol::SYMBOL_TYPE_INPUT )
882                     {
883                         ++num;
884                     }
885                 }
886 
887                 return num;
888             }
889 
890             //------------------------------------------------------------------------
891 
SearchBindSymbol(BindSymbol * symbol,const u8 symbol_index) const892             bool Shader::SearchBindSymbol(
893                 BindSymbol* symbol,
894                 const u8 symbol_index ) const
895             {
896                 const BindSymbol::ShaderType shaderType = symbol->shaderType;
897 
898                 const int shader_index = ( shaderType == BindSymbol::SHADER_TYPE_GEOMETRY )
899                     ? GetGeoShaderIndex() : GetVtxShaderIndex();
900 
901                 NN_GR_ASSERT(  0 <= shader_index && shader_index < m_ExeImageInfoNum );
902 
903                 // プログラム情報
904                 const ExeImageInfo* exe_info = m_ExeImageInfo[ shader_index ];
905 
906                 // シンボル情報
907                 struct BindSymbolInfo { u32 nameIndex; u32 regIndex; };
908                 const BindSymbolInfo* bind_symbol_info =
909                     reinterpret_cast< const BindSymbolInfo* >(
910                         reinterpret_cast< const u8* >( exe_info ) + exe_info->bindSymbolOffset );
911 
912                 // 文字列情報
913                 const char* string =
914                     reinterpret_cast< const char* >(
915                         reinterpret_cast< const u8* >( exe_info ) + exe_info->stringOffset );
916 
917                 int index = -1;
918 
919                 // 検索
920                 for ( int i = 0; i < exe_info->bindSymbolCount; ++i )
921                 {
922                     int regStart = bind_symbol_info[ i ].regIndex & 0x0000ffff;
923 
924                     // Bool registers
925                     if ( 120 <= regStart && regStart < 136 )
926                     {
927                         ++index;
928                     }
929                     // Integer registers
930                     else if ( 112 <= regStart && regStart < 115 )
931                     {
932                         ++index;
933                     }
934                     // Constant registers
935                     else if ( 16 <= regStart && regStart < 111 )
936                     {
937                         ++index;
938                     }
939                     // Input registers
940                     else if ( regStart <  15 )
941                     {
942                         ++index;
943                     }
944                     else
945                     {
946                         return false;
947                     }
948 
949                     if ( index == symbol_index )
950                     {
951                         const BindSymbolInfo& info = bind_symbol_info[ i ];
952 
953                         symbol->name  = &string[ info.nameIndex ];
954                         symbol->start = (info.regIndex & 0x0000ffff);
955                         symbol->end   = (info.regIndex & 0xffff0000) >> 16;
956 
957                         if ( 120 <= symbol->start )
958                         {
959                             symbol->start -= 120;
960                             symbol->end   -= 120;
961 
962                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_BOOL;
963                         }
964                         else if ( 112 <= symbol->start )
965                         {
966                             symbol->start -= 112;
967                             symbol->end -= 112;
968 
969                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INTEGER;
970                         }
971                         else if (  16 <= symbol->start )
972                         {
973                             symbol->start -=  16;
974                             symbol->end -=  16;
975 
976                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_FLOAT;
977                         }
978                         else
979                         {
980                             return symbol->symbolType == BindSymbol::SYMBOL_TYPE_INPUT;
981                         }
982                     }
983                 }
984 
985                 return false;
986             }
987 
988         } //namespace CTR
989     } //namespace gr
990 } //namespace nn
991