1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gr_Shader.h
4 
5   Copyright (C)2010 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 25895 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_GR_SHADER_H_
17 #define NN_GR_SHADER_H_
18 
19 #include <nn/gr/CTR/gr_Prefix.h>
20 #include <nn/gr/CTR/gr_BindSymbol.h>
21 
22 namespace nn
23 {
24     namespace gr
25     {
26         namespace CTR
27         {
28 
29             /*!
30                 @brief シェーダーバイナリ設定のためのクラスです。
31              */
32             class Shader
33             {
34             public :
35                 /*!
36                     @brief シェーダーバイナリをもとに、コマンド生成用の情報をセットアップします。
37                            ※バイナリのコピーはしないので、コマンド生成までバイナリは破棄しないで下さい。
38                            指定されたインデクスが有効なシェーダーでない場合、ASSERTです。
39                            指定するインデクスは、ctr_VertexShaderLinker32.exeでのリンク時に生成される
40                            MAPファイルを参考にして下さい。
41                            geo_shader_indexについては、-1を指定することでジオメトリシェーダーを無効化することが出来ます。
42 
43                     @param [in] shader_binary ctr_VertexShaderLinker32.exeでリンクされたシェーダーバイナリです。
44                     @param [in] vtx_shader_index 有効にする頂点シェーダーのインデクスです。
45                     @param [in] geo_shader_index 有効にするジオメトリシェーダーシェーダーのインデクスです。
46                 */
47                 void SetupBinary( const void* shader_binary, const int vtx_shader_index, const int geo_shader_index );
48 
49             public :
50                 /*!
51                     @brief 頂点シェーダーにブールレジスタの値を設定します。
52 
53                     @param [in] symbol   頂点シェーダのブール型のシンボルです。
54                     @param [in] isEnable 有効にするときは true、そうでないときは false にします。
55                  */
SetUniformBool(const BindSymbolVSBool & symbol,bool isEnable)56                 void SetUniformBool( const BindSymbolVSBool& symbol, bool isEnable )
57                 {
58                     m_VtxShaderBoolMapUniform = ( m_VtxShaderBoolMapUniform & ~( 1 << symbol.start ) ) | ( ( isEnable ? 1 : 0 ) << symbol.start );
59                 }
60 
61                 /*!
62                     @brief ジオメトリシェーダーにブールレジスタの値を設定します。
63 
64                     @param [in] symbol   ジオメトリシェーダのブール型のシンボルです。
65                     @param [in] isEnable 有効にするときは true、そうでないときは false にします。
66                  */
SetUniformBool(const BindSymbolGSBool & symbol,bool isEnable)67                 void SetUniformBool( const BindSymbolGSBool& symbol, bool isEnable )
68                 {
69                     m_GeoShaderBoolMapUniform = ( m_GeoShaderBoolMapUniform & ~( 1 << symbol.start ) ) | ( ( isEnable ? 1 : 0 ) << symbol.start );
70                 }
71 
72                 /*!
73                     @brief 描画モードの設定を行います。
74                            デフォルトはGL_TRIANGLESです。
75                            PICA_DATA_DRAW_TRIANGLES、PICA_DATA_DRAW_TRIANGLE_STRIP、PICA_DATA_DRAW_TRIANGLE_FANのいずれかを指定します。
76 
77                     @param[in] draw_mode 設定する描画モード
78                  */
SetDrawMode(const PicaDataDrawMode draw_mode)79                 void SetDrawMode( const PicaDataDrawMode draw_mode )
80                 {
81                     m_DrawMode = draw_mode;
82                 }
83 
84             public :
85                 /*!
86                     @brief シェーダー切り替えに必要な全てのコマンドを生成します。
87                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
88 
89                     @param[in] command 描画コマンドの書き込み先の先頭アドレスです。
90 
91                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
92                  */
93                 u32* MakeFullCommand( u32* command ) const;
94 
95             public :
96                 /*!
97                     @brief 頂点シェーダーのブールレジスタへ値を設定するコマンドを生成します。
98                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
99 
100                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
101 
102                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
103                  */
MakeVtxBoolMapCommand(u32 * command)104                 u32* MakeVtxBoolMapCommand( u32* command ) const
105                 {
106                     *command++ = 0x7fff0000 | m_VtxShaderBoolMapUniform;
107                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_BOOL ); // 0x2b0
108                     return command;
109                 }
110 
111                 /*!
112                     @brief ジオメトリシェーダーのブールレジスタへ値を設定するコマンドを生成します。
113                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
114 
115                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
116                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
117                  */
MakeGeoBoolMapCommand(u32 * command)118                 u32* MakeGeoBoolMapCommand( u32* command ) const
119                 {
120                     *command++ = 0x7fff0000 | m_GeoShaderBoolMapUniform;
121                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_BOOL ); // 0x280
122                     return command;
123                 }
124 
125                 /*!
126                     @brief ジオメトリシェーダー使用設定コマンドを生成します。
127                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
128                            ジオメトリシェーダーの有効/無効を設定するときに必要なダミーコマンド、
129                            有効、無効の設定コマンドなどが含まれます。
130                     @param[in] command 描画コマンドの書き込み先の先頭アドレスです。
131                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
132                  */
133                 u32* MakePrepareCommand( u32* command ) const;
134 
135                 /*!
136                     @brief 頂点シェーダーについて、プログラムロードのコマンドを生成します。
137                            エントリポイントのアドレス、シェーダーバイナリ内の実行コード部分などが含まれます。
138                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
139 
140                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
141                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
142                  */
143                 u32* MakeVtxProgramCommand( u32* command ) const;
144 
145                 /*!
146                     @brief ジオメトリシェーダーについて、プログラムロードのコマンドを生成します。
147                            エントリポイントのアドレス、シェーダーバイナリ内の実行コード部分などが含まれます。
148                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
149 
150                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
151 
152                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
153                  */
154                 u32* MakeGeoProgramCommand( u32* command ) const;
155 
156                 /*!
157                     @brief 頂点シェーダーについて、Swizzleパターンロードのコマンド生成します。
158                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
159 
160                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
161 
162                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
163                  */
MakeVtxSwizzleCommand(u32 * command)164                 u32* MakeVtxSwizzleCommand( u32* command ) const
165                 {
166                     *command++ = 0;
167                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_PROG_SWIZZLE_ADDR );
168                     return MakeLoadCommand_( command, PICA_REG_VS_PROG_SWIZZLE_DATA0, m_Swizzle, m_SwizzleCount );
169                 }
170 
171                 /*!
172                     @brief ジオメトリシェーダーについて、Swizzleパターンロードのコマンド生成します。
173                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
174 
175                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
176 
177                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
178                  */
MakeGeoSwizzleCommand(u32 * command)179                 u32* MakeGeoSwizzleCommand( u32* command ) const
180                 {
181                     *command++ = 0;
182                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_GS_PROG_SWIZZLE_ADDR );
183                     return MakeLoadCommand_( command, PICA_REG_GS_PROG_SWIZZLE_DATA0, m_Swizzle, m_SwizzleCount );
184                 }
185 
186                 /*!
187                     @brief 頂点シェーダーについて、定数レジスタをUniformするコマンド生成します。
188                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
189 
190                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
191 
192                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
193                  */
MakeVtxConstRgCommand(u32 * command)194                 u32* MakeVtxConstRgCommand( u32* command ) const
195                 {
196                     std::memcpy( command, m_CmdCacheVtxConst, m_CmdCacheVtxConstNum * sizeof( u32 ) );
197                     return command + m_CmdCacheVtxConstNum;
198                 }
199 
200                 /*!
201                     @brief ジオメトリシェーダーについて、定数レジスタをUniformするコマンド生成します。
202                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
203 
204                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
205 
206                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
207                  */
MakeGeoConstRgCommand(u32 * command)208                 u32* MakeGeoConstRgCommand( u32* command ) const
209                 {
210                     std::memcpy( command, m_CmdCacheGeoConst, m_CmdCacheGeoConstNum * sizeof( u32 ) );
211                     return command + m_CmdCacheGeoConstNum;
212                 }
213 
214                 /*!
215                     @brief シェーダーの出力属性を設定するコマンド生成します。
216                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
217 
218                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
219                     @param[in] is_geometry_shader ジオメトリシェーダーについてのコマンドを生成したい場合、trueを設定します。
220 
221                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
222                  */
MakeOutAttrCommand(u32 * command)223                 u32* MakeOutAttrCommand( u32* command ) const
224                 {
225                     std::memcpy( command, m_CmdCacheOutAttr, m_CmdCacheOutAttrNum * sizeof( u32 ) );
226                     return command + m_CmdCacheOutAttrNum;
227                 }
228 
229             public : // バイナリからの情報を取得
230                 /*!
231                    @brief シンボル名から、シンボル情報への変換をおこないます。
232                          「シェーダーコード内で#pragma bind_symbol() で設定したシンボル名」を引数に与えることで、
233                           シンボルの型情報とバインドされているレジスタ番号が取得できます。
234                           SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
235 
236                  * @param[out] symbol             シンボル名によって検索されたシンボルです。
237                  * @param[in]  name               検索したいシンボル名です。
238 
239                  * @return     検索対象が見つかった場合、trueを返します。
240                  */
241                 bool SearchBindSymbol(
242                     BindSymbol*      symbol,
243                     const char*      name ) const;
244 
245                  /*!
246                     @brief 指定された型のシンボルについて、いくつあるか検索します。
247                            シェーダーコード内で#pragma bind_symbol() されているもののうち、
248                            指定された型のものがいくつあるか検索します。
249                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
250 
251                     @param[in]  shader_type 検索したいシェーダーの種類です。
252                     @param[in]  symbol_type 検索したい型です。
253 
254                     @return     見つかったシンボルの数を返します。
255                  */
256                 u32  SearchBindSymbolNum(
257                     const BindSymbol::ShaderType shader_type,
258                     const BindSymbol::SymbolType symbol_type ) const;
259 
260                 /*!
261                    @brief 指定された型のシンボルについて、インデックス(0からシンボル数-1)からシンボル情報への変換を行います。
262                           シェーダーコード内で、#pragma bind_symbol() されている順番で、
263                           0,1,...シンボル数-1というインデックスが振られます。
264                           指定されたインデックスを検索し、見つかったシンボルの情報を取得できます。
265                           SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
266 
267                    @param[out] symbol             インデックスに対応するシンボルです。
268                    @param[in]  symbol_index       検索したいインデックスです。
269 
270                    @return     検索対象が見つかった場合、trueを返します。
271                  */
272                 bool SearchBindSymbol(
273                     BindSymbol*      symbol,
274                     const u8         symbol_index ) const;
275 
276             public : // 設定の取得
277                 /*!
278                     @brief シェーダーバイナリに含まれる実行可能シェーダーの数を取得します。
279 
280                     @return 実行可能シェーダーの数です。
281                  */
GetShaderNum()282                 u8 GetShaderNum()           const
283                 {
284                     return m_ExeImageInfoNum;
285                 }
286 
287                 /*!
288                     @brief  ジオメトリシェーダーが有効かどうかを取得します。
289 
290                     @return EnableGeoShader()によって有効化されていれば、true です。
291                     @see    EnableGeoShader()、DisableGeoShader()
292                  */
IsEnableGeoShader()293                 bool IsEnableGeoShader()    const
294                 {
295                     return ( 0 <= GetGeoShaderIndex() );
296                 }
297 
298                 /*!
299                     @brief  有効になっている頂点シェーダーのインデックスを取得します。
300 
301                     @return EnableVtxShader()によって有効化されているシェーダーインデックスです。
302                     @see    EnableVtxShader()
303                  */
304 
GetVtxShaderIndex()305                 int GetVtxShaderIndex()     const
306                 {
307                     return m_VtxShaderIndex;
308                 }
309 
310                 /*!
311                     @brief  有効になっている有効になっているジオメトリシェーダーのインデックスを取得します。
312 
313                     @return EnableGeoShader()によって有効化されているシェーダーインデックス
314                     @see    EnableGeoShader()、DisableGeoShader()
315                  */
GetGeoShaderIndex()316                 int GetGeoShaderIndex()     const
317                 {
318                     return m_GeoShaderIndex;
319                 }
320 
321                 /*!
322                     @brief 頂点シェーダーに設定されるブールマップを取得します。
323 
324                     @return ブールマップです。
325                  */
GetVtxShaderBoolMapUniform()326                 u32 GetVtxShaderBoolMapUniform() const
327                 {
328                     return m_VtxShaderBoolMapUniform;
329                 }
330 
331                 /*!
332                     @brief ジオメトリシェーダーに設定されるブールマップを取得します。
333 
334                     @return ブールマップです。
335                  */
GetGeoShaderBoolMap()336                 u32 GetGeoShaderBoolMap()    const
337                 {
338                     return m_GeoShaderBoolMapUniform;
339                 }
340 
341             private :
342                 /*!
343                     @brief クラス定数です。
344                  */
345                 enum
346                 {
347                     //! 実行可能シェーダーの最大数です。
348                     EXE_IMAGE_MAX = 32,
349 
350                     //! Swizzleパターンの最大数です。
351                     SWIZZLE_PATTERN_MAX = 128,
352 
353                     //! 0x251に設定するダミーコマンドの数です。
354                     DUMMY_DATA_NUM_251 = 10,
355 
356                     //! 0x200に設定するダミーコマンドの数です。
357                     DUMMY_DATA_NUM_200 = 30,
358 
359                     //! ダミーコマンドなど、パディングにつかう値です。
360                     PADDING_DATA = 0xead0fead,
361 
362                     //! 出力属性のコマンドの最大数です。
363                     OUT_ATTR_COMMAND_MAX = 48,
364 
365                     //! 定数レジスタコマンドの最大数です。
366                     CONST_REG_COMMAND_MAX = 96 * 6 + 5 * 2
367                 };
368 
369             private:
370 
371                 /*!
372                     @brief 定数レジスタをUniformするコマンド生成します。
373                            SetupBinaryでシェーダーバイナリを設定した後に呼ぶようにして下さい。
374 
375                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
376                     @param[in] is_geometry_shader ジオメトリシェーダーについてのコマンドを生成したい場合、trueを設定します。
377                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
378                  */
379 
380                 u32* MakeConstRgCommand_(
381                     u32* command,
382                     const bool is_geometry_shader = false );
383 
384                 /*!
385                     @brief シェーダーの出力属性を設定するコマンド生成します。
386 
387                     @param[in] command            描画コマンドの書き込み先の先頭アドレスです。
388                     @param[in] is_geometry_shader ジオメトリシェーダーについてのコマンドを生成したい場合、trueを設定します。
389 
390                     @return    書き込まれた描画コマンドの終端の次のアドレスを返します。
391                  */
392                 u32* MakeOutAttrCommand_( u32* command );
393 
394                 /*!
395                     @brief ひとまとまりのデータを指定されたレジスタに送信するコマンドを生成します。SEQ、BEには非対応です。
396 
397                     @param   command        [out] コマンドを追加するバッファのアドレスです。
398                     @param   load_reg       [in]  送信するレジスタです。
399                     @param   src_buffer_ptr [in]  送信したいデータのバッファの先頭アドレスです。
400                     @param   src_data_num   [in]  送信したいデータの数です。
401 
402                     @return                       書き込まれた描画コマンドの終端の次のアドレスを返します。
403                  */
404                 u32* MakeLoadCommand_( u32* command,
405                                        const u32  load_reg,
406                                        const u32* src_buffer_ptr,
407                                        const u32  src_size ) const;
408 
409                 /*!
410                     @brief 指定されたレジスタにダミーコマンドを送信するコマンドを生成します。
411 
412                     @param   command        [out] コマンドを追加するバッファのアドレス
413                     @param   load_reg       [in]  送信するレジスタ
414                     @param   data_num       [in]  送信したいデータの数
415 
416                     @return                       書き込まれた描画コマンドの終端の次のアドレスを返します。
417                  */
418                 u32* MakeDummyCommand_( u32* command,
419                                         const u32 load_reg,
420                                         const u32 data_num ) const;
421 
422                 /*!
423                     @brief シェーダーバイナリ内の実行コード部分をあらわす構造体です。
424                  */
425                 struct ExeImageInfo
426                 {
427                     u32 signature;
428                     u16 version;
429                     u8  isGeoShader;
430                     u8  outputMaps;
431                     u32 mainAddress;
432                     u32 endAddress;
433                     u32 maskInputOutput;
434                     u8  gsDataMode;
435                     u8  gsVertexStartIndex;
436                     u8  gsPatchSize;
437                     u8  gsVertexNum;
438                     u32 setupOffset;
439                     u32 setupCount;
440                     u32 labelOffset;
441                     u32 labelCount;
442                     u32 outMapOffset;
443                     u32 outMapCount;
444                     u32 bindSymbolOffset;
445                     u32 bindSymbolCount;
446                     u32 stringOffset;
447                     u32 stringCount;
448                 };
449 
450                 /*!
451                     @brief 有効になっている頂点シェーダーのインデックスです。
452                 */
453                 int m_VtxShaderIndex;
454 
455                 /*!
456                     @brief 有効になっているジオメトリシェーダーのインデックスです。
457                 */
458                 int m_GeoShaderIndex;
459 
460                 /*!
461                     @brief シェーダーバイナリ内の、実行可能シェーダーの数です。
462                 */
463                 u8 m_ExeImageInfoNum;
464                 NN_PADDING3;
465 
466                 /*!
467                     @brief シェーダーバイナリ内の、実行可能シェーダーの情報へのポインタを保持します。
468                 */
469                 const ExeImageInfo* m_ExeImageInfo[ EXE_IMAGE_MAX ];
470 
471                 /*!
472                     @brief シェーダーバイナリ内の、シェーダーの実行コード部分へのポインタです。
473                 */
474                 const u32* m_Instruction;
475 
476                 /*!
477                     @brief シェーダーバイナリ内の、シェーダーの実行コード部分のサイズです。
478                 */
479                 u32 m_InstructionCount;
480 
481                 /*!
482                     @brief Swizzleパターンをコマンド形式に表現したものです。
483                 */
484                 u32 m_Swizzle[ SWIZZLE_PATTERN_MAX ];
485 
486                 /*!
487                     @brief Swizzleパターンの数です。
488                 */
489                 u32 m_SwizzleCount;
490 
491                 /*!
492                     @brief 描画モードをあらわします。デフォルトはPICA_DATA_DRAW_TRIANGLESです。
493                 */
494                 PicaDataDrawMode m_DrawMode;
495                 NN_PADDING3;
496 
497                 /*!
498                     @brief ユニフォームされる頂点シェーダーのブールマップです。
499                 */
500                 u32 m_VtxShaderBoolMapUniform;
501 
502                 /*!
503                     @brief ユニフォームされるジオメトリシェーダーのブールマップです。
504                 */
505                 u32 m_GeoShaderBoolMapUniform;
506 
507                 /*!
508                     @brief 出力属性のコマンドキャッシュです。
509                 */
510                 u32 m_CmdCacheOutAttr[ OUT_ATTR_COMMAND_MAX ];
511 
512                 /*!
513                     @brief 出力属性のコマンド数です。
514                 */
515                 u32 m_CmdCacheOutAttrNum;
516 
517                 /*!
518                     @brief 頂点シェーダーの定数レジスタのコマンドキャッシュです。
519                 */
520                 u32 m_CmdCacheVtxConst[ CONST_REG_COMMAND_MAX ];
521 
522                 /*!
523                     @brief 頂点シェーダーの定数レジスタのコマンド数です。
524                 */
525                 u32 m_CmdCacheVtxConstNum;
526 
527                 /*!
528                     @brief ジオメトリシェーダーの定数レジスタのコマンドキャッシュです。
529                 */
530                 u32 m_CmdCacheGeoConst[ CONST_REG_COMMAND_MAX ];
531 
532                 /*!
533                     @brief ジオメトリシェーダーの定数レジスタのコマンド数です。
534                 */
535                 u32 m_CmdCacheGeoConstNum;
536             };
537 
538         } // namespace CTR
539     } // namespace gr
540 } // namespace nn
541 
542 #endif // NN_GR_SHADER_H_
543