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