1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_ShaderBinaryInfo.cpp
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: 31311 $
16 *---------------------------------------------------------------------------*/
17
18 #include "precompiled.h"
19
20 #include <nw/gfx/gfx_CommandUtil.h>
21 #include <nw/gfx/gfx_ShaderBinaryInfo.h>
22
23 namespace nw
24 {
25 namespace gfx
26 {
27
28 //---------------------------------------------------------------------------
29 void
AnalyzeBinary()30 ShaderBinaryInfo::AnalyzeBinary()
31 {
32 const u32* binary = m_pShaderBinary;
33
34 NW_ASSERT( *binary == ut::ReverseEndian('DVLB') );
35 ++binary;
36
37 NW_ASSERT( *binary < EXE_IMAGE_MAX );
38 m_ExeImageCount = *binary;
39 ++binary;
40
41 for ( int i = 0; i < m_ExeImageCount; ++i )
42 {
43 m_ExeImageInfo[ i ] = reinterpret_cast< const ExeImageInfo* >( (u8*)m_pShaderBinary + *binary );
44 NW_ASSERT( m_ExeImageInfo[ i ]->signature == ut::ReverseEndian('DVLE') );
45
46 if ( m_ExeImageInfo[ i ]->isGeometryShader )
47 {
48 ++m_GeometryShaderCount;
49 }
50
51 ++binary;
52 }
53
54 const u32* packageInfo = binary;
55 NW_ASSERT( *binary == ut::ReverseEndian('DVLP') ); // DVLP
56 ++binary;
57 ++binary;
58
59 m_pInstruction = static_cast<const u32*>( ut::AddOffsetToPtr( packageInfo, *binary ) );
60 ++binary;
61
62 m_InstructionCount = *binary;
63 ++binary;
64
65 const u32* swizzle = static_cast<const u32*>( ut::AddOffsetToPtr( packageInfo, *binary ) );
66 ++binary;
67
68 m_SwizzleCount = *binary;
69 NW_ASSERT( m_SwizzleCount < SWIZZLE_PATTERN_MAX );
70 ++binary;
71
72 // リンカ用のメタ情報はスキップして値だけ保存する。
73 for ( int i = 0; i < m_SwizzleCount; i++ )
74 {
75 m_Swizzle[ i ] = swizzle[ i * 2 ];
76 }
77 }
78
79 //---------------------------------------------------------------------------
80 s32
GetCommonCommandSize() const81 ShaderBinaryInfo::GetCommonCommandSize() const
82 {
83 s32 size = 0;
84
85 // PutEnableMirroringShaderSetting の分。
86 size += sizeof(u32) * 2;
87
88 size += GetSwizzleCommandSize();
89 size += GetProgramCommandSize();
90
91 return size;
92 }
93
94
95 //---------------------------------------------------------------------------
96 s32
GetShaderProgramCommandSize(s32 vertexIndex,s32 geometryIndex) const97 ShaderBinaryInfo::GetShaderProgramCommandSize( s32 vertexIndex, s32 geometryIndex ) const
98 {
99 s32 size = 0;
100
101 size += 2 * sizeof(u32); // PutEnableMirroringShaderSetting の分
102
103 size += this->GetConstRegCommandSize( vertexIndex );
104
105 if ( geometryIndex >= 0 )
106 {
107 size += this->GetConstRegCommandSize( geometryIndex );
108 }
109
110 size += this->GetOutAttrCommandSize( vertexIndex, geometryIndex );
111
112 return size;
113 }
114
115 //---------------------------------------------------------------------------
116 s32
GetProgramCommandSize() const117 ShaderBinaryInfo::GetProgramCommandSize() const
118 {
119 enum { VS_INSTRUCTION_MAX = 512 };
120
121 u32 vertexInstructionCount = ut::Min( m_InstructionCount, u32(VS_INSTRUCTION_MAX) );
122
123 s32 size = 0;
124
125 size += 2 * sizeof(u32);
126 size += this->GetLoadCommandSize( vertexInstructionCount );
127 size += 2 * sizeof(u32);
128
129 if ( this->GetGeometryShaderCount() > 0 )
130 {
131 size += 2 * sizeof(u32);
132 size += this->GetLoadCommandSize( m_InstructionCount );
133 size += 2 * sizeof(u32);
134 }
135
136 return size;
137 }
138
139 //---------------------------------------------------------------------------
140 s32
GetSwizzleCommandSize() const141 ShaderBinaryInfo::GetSwizzleCommandSize() const
142 {
143 s32 size = 0;
144
145 size += 2 * sizeof(u32);
146 size += this->GetLoadCommandSize( m_SwizzleCount );
147
148 if ( this->GetGeometryShaderCount() > 0 )
149 {
150 size += 2 * sizeof(u32);
151 size += this->GetLoadCommandSize( m_SwizzleCount );
152 }
153
154 return size;
155 }
156
157 //---------------------------------------------------------------------------
158 s32
GetPrepareCommandSize() const159 ShaderBinaryInfo::GetPrepareCommandSize() const
160 {
161 return 0;
162 }
163
164 //---------------------------------------------------------------------------
165 s32
GetConstRegCommandSize(s32 shaderIndex) const166 ShaderBinaryInfo::GetConstRegCommandSize(s32 shaderIndex) const
167 {
168 s32 size = 0;
169 const s32 INT_COMMAND_SIZE = 2;
170 const s32 FLOAT_COMMAND_SIZE = 6;
171
172 bool isGeometry = this->IsGeometryShader( shaderIndex );
173
174 // プログラム情報
175 const ExeImageInfo* exeInfo = m_ExeImageInfo[ shaderIndex ];
176
177 // 定数レジスタ情報
178 struct SetupInfo
179 {
180 u16 type;
181 u16 index;
182 u32 value[4];
183 };
184
185 enum { TYPE_BOOL = 0, TYPE_INT = 1, TYPE_FLOAT = 2 };
186
187 const SetupInfo* setupInfoTable =
188 static_cast<const SetupInfo*>( ut::AddOffsetToPtr( exeInfo, exeInfo->setupOffset) );
189
190 // 定数レジスタのコマンド生成
191 for ( int i = 0; i < exeInfo->setupCount; ++i )
192 {
193 const SetupInfo& info = setupInfoTable[ i ];
194
195 switch ( info.type )
196 {
197 case TYPE_BOOL:
198 break;
199
200 case TYPE_INT:
201 size += INT_COMMAND_SIZE * sizeof(u32);
202 break;
203
204 case TYPE_FLOAT:
205 size += FLOAT_COMMAND_SIZE * sizeof(u32);
206 break;
207 }
208 }
209
210 return size;
211 }
212
213 //---------------------------------------------------------------------------
214 s32
GetOutAttrCommandSize(s32 vertexIndex,s32 geometryIndex) const215 ShaderBinaryInfo::GetOutAttrCommandSize(s32 vertexIndex, s32 geometryIndex) const
216 {
217 NW_UNUSED_VARIABLE(vertexIndex);
218
219 const s32 GEOMETRY_SETTING_COMMAND_SIZE = 8;
220 const s32 SHADER_PROGRAM_COMMAND_SIZE = 24;
221 const s32 GEOMETRY_COMMAND_SIZE = 6;
222
223 s32 size = 0;
224
225 bool hasGeometry = geometryIndex >= 0;
226 u32 geometrySettingCommandSize = (GEOMETRY_SETTING_COMMAND_SIZE - (hasGeometry ? 0 : 2)) * sizeof(u32);
227
228 size += geometrySettingCommandSize;
229 size += SHADER_PROGRAM_COMMAND_SIZE * sizeof(u32);
230
231 if ( hasGeometry )
232 {
233 size += GEOMETRY_COMMAND_SIZE * sizeof(u32);
234 }
235
236 return size;
237 }
238
239
240 //---------------------------------------------------------------------------
241 // NOTE: コマンドのサイズが変わる場合は、必ず GetCommonCommandSize も合わせて修正する。
242 s32
BuildCommonCommand(u32 * bufferAddress,u32 bufferSize) const243 ShaderBinaryInfo::BuildCommonCommand( u32* bufferAddress, u32 bufferSize ) const
244 {
245 SafeBuffer buffer(bufferAddress, bufferSize);
246
247 // シェーダバイナリの転送コマンドを生成します。
248 // その他の頂点の設定コマンド等は、ShaderProgramDescription 側に持ちます。
249
250 // ジオメトリシェーダのインストラクションの前方部分には、
251 // 頂点シェーダと同じ命令が格納されているので、ResShaderBinary が
252 // 同じであればシェーダバイナリの再転送は必要ない。
253 //
254 // この為、ジオメトリシェーダがある場合には必ずジオメトリ分のバイナリも転送する。
255
256 if ( this->GetGeometryShaderCount() > 0 )
257 {
258 this->PutEnableMirroringShaderSetting( buffer, false );
259 }
260 else
261 {
262 this->PutEnableMirroringShaderSetting( buffer, true );
263 }
264
265 this->BuildSwizzleCommand( buffer );
266 this->BuildProgramCommand( buffer );
267
268 return buffer.UsedSize();
269 }
270
271
272 //---------------------------------------------------------------------------
273 // NOTE: コマンドのサイズが変わる場合は、必ず GetProgramCommandSize も合わせて修正する。
274 void
BuildProgramCommand(SafeBuffer & buffer) const275 ShaderBinaryInfo::BuildProgramCommand( SafeBuffer& buffer ) const
276 {
277 // あらかじめ、PutEnableMirroringShaderSetting でミラーリングが有効に
278 // 設定した状態で呼び出される事が前提となっています。
279
280 // この関数から抜ける際には、MirroringShaderSetting の値は不定となります。
281
282 // まず先頭から512命令以内の部分は、頂点・ジオメトリ共用部分として送信する。
283
284 enum { VS_INSTRUCTION_MAX = 512 };
285
286 u32 vertexInstructionCount = ut::Min( m_InstructionCount, u32(VS_INSTRUCTION_MAX) );
287
288 const u32 VS_COMMAND[] =
289 {
290 0,
291 internal::MakeCommandHeader( PICA_REG_VS_PROG_ADDR, 1, false, 0xF )
292 };
293
294 buffer.Write( &VS_COMMAND[0], sizeof(VS_COMMAND) );
295
296 // 頂点部分のインストラクションのロード。
297 this->PutLoadCommand( buffer,
298 PICA_REG_VS_PROG_DATA0,
299 &m_pInstruction[ 0 ],
300 vertexInstructionCount );
301
302 const u32 VS_RENEWAL_COMMAND[] =
303 {
304 1,
305 internal::MakeCommandHeader( PICA_REG_VS_PROG_RENEWAL_END, 1, false, 0xF )
306 };
307
308 buffer.Write( &VS_RENEWAL_COMMAND[0], sizeof(VS_RENEWAL_COMMAND) );
309
310 if ( this->GetGeometryShaderCount() > 0 )
311 {
312 const u32 GS_COMMAND[] =
313 {
314 0,
315 internal::MakeCommandHeader( PICA_REG_GS_PROG_ADDR, 1, false, 0xF )
316 };
317
318 buffer.Write( &GS_COMMAND[0], sizeof(GS_COMMAND) );
319
320 // 頂点部分のインストラクションのロード。
321 this->PutLoadCommand( buffer,
322 PICA_REG_GS_PROG_DATA0,
323 &m_pInstruction[ 0 ],
324 m_InstructionCount );
325
326 const u32 GS_RENEWAL_COMMAND[] =
327 {
328 1,
329 internal::MakeCommandHeader( PICA_REG_GS_PROG_RENEWAL_END, 1, false, 0xF )
330 };
331
332 buffer.Write( &GS_RENEWAL_COMMAND[0], sizeof(GS_RENEWAL_COMMAND) );
333 }
334 }
335
336
337 //---------------------------------------------------------------------------
338 // NOTE: コマンドのサイズが変わる場合は、必ず GetSwizzleCommandSize も合わせて修正する。
339 void
BuildSwizzleCommand(SafeBuffer & buffer) const340 ShaderBinaryInfo::BuildSwizzleCommand( SafeBuffer& buffer ) const
341 {
342 // あらかじめ、PutEnableMirroringShaderSetting でミラーリングが有効に
343 // 設定した状態で呼び出される事が前提となっています。
344
345 const u32 COMMAND[] =
346 {
347 0,
348 internal::MakeCommandHeader( PICA_REG_VS_PROG_SWIZZLE_ADDR, 1, false, 0xF )
349 };
350
351 buffer.Write( &COMMAND[0], sizeof(COMMAND) );
352
353 NW_ASSERT( m_SwizzleCount > 0 );
354
355 // Swizzleパターンのロード
356 this->PutLoadCommand( buffer,
357 PICA_REG_VS_PROG_SWIZZLE_DATA0,
358 &m_Swizzle[0],
359 m_SwizzleCount );
360
361 if ( this->GetGeometryShaderCount() > 0 )
362 {
363 const u32 GS_COMMAND[] =
364 {
365 0,
366 internal::MakeCommandHeader( PICA_REG_GS_PROG_SWIZZLE_ADDR, 1, false, 0xF )
367 };
368
369 buffer.Write( &GS_COMMAND[0], sizeof(GS_COMMAND) );
370
371 NW_ASSERT( m_SwizzleCount > 0 );
372
373 // Swizzleパターンのロード
374 this->PutLoadCommand( buffer,
375 PICA_REG_GS_PROG_SWIZZLE_DATA0,
376 &m_Swizzle[0],
377 m_SwizzleCount );
378 }
379 }
380
381
382 //---------------------------------------------------------------------------
383 // NOTE: コマンドのサイズが変わる場合は、必ず GetShaderProgramCommandSize も合わせて修正する。
384 s32
BuildShaderProgramCommand(s32 vertexIndex,s32 geometryIndex,u32 * bufferAddress,u32 bufferSize) const385 ShaderBinaryInfo::BuildShaderProgramCommand( s32 vertexIndex, s32 geometryIndex, u32* bufferAddress, u32 bufferSize ) const
386 {
387 SafeBuffer buffer(bufferAddress, bufferSize);
388
389 NW_ASSERT( ! this->IsGeometryShader( vertexIndex ) );
390 NW_ASSERT( 0 <= vertexIndex && vertexIndex < this->GetShaderCount() );
391 NW_ASSERT( geometryIndex < 0 || this->IsGeometryShader( geometryIndex ) );
392 NW_ASSERT( geometryIndex < this->GetShaderCount() );
393
394 if ( geometryIndex < 0 )
395 {
396 this->PutEnableMirroringShaderSetting( buffer, true );
397 }
398 else
399 {
400 this->PutEnableMirroringShaderSetting( buffer, false );
401 }
402
403 this->BuildConstRegCommand( buffer, vertexIndex );
404
405 if ( geometryIndex >= 0 )
406 {
407 this->BuildConstRegCommand( buffer, geometryIndex );
408 }
409
410 this->BuildOutAttrCommand( buffer, vertexIndex, geometryIndex );
411
412 return buffer.UsedSize();
413 }
414
415
416 //---------------------------------------------------------------------------
417 // NOTE: コマンドのサイズが変わる場合は、必ず GetPrepareCommandSize も合わせて修正する。
418 void
BuildPrepareCommand(SafeBuffer & buffer) const419 ShaderBinaryInfo::BuildPrepareCommand( SafeBuffer& buffer ) const
420 {
421 NW_UNUSED_VARIABLE(buffer);
422
423 // tugal では次のコマンドを生成している。
424 // ・ジオメトリシェーダの有効化とパイプライン掃除用のダミーコマンド。
425 // ・0x25e[8:9] へのプリミティブ形状設定。
426 // ・0x244 への頂点・ジオメトリ設定のミラーリング設定。
427 // NW では、これらは必要な場合のみ設定するようにする。
428 }
429
430
431 //---------------------------------------------------------------------------
432 // NOTE: コマンドのサイズが変わる場合は、必ず GetConstRegCommandSize も合わせて修正する。
433 void
BuildConstRegCommand(SafeBuffer & buffer,s32 shaderIndex) const434 ShaderBinaryInfo::BuildConstRegCommand( SafeBuffer& buffer, s32 shaderIndex ) const
435 {
436 bool isGeometry = this->IsGeometryShader( shaderIndex );
437
438 u32 regFloat = PICA_REG_VS_FLOAT_ADDR; // 0x2c0
439 u32 regInteger = PICA_REG_VS_INT0; // 0x2b1
440
441 if ( isGeometry )
442 {
443 regFloat = PICA_REG_GS_FLOAT_ADDR; // 0x290
444 regInteger = PICA_REG_GS_INT0; // 0x281
445 }
446
447 // プログラム情報
448 const ExeImageInfo* exeInfo = m_ExeImageInfo[ shaderIndex ];
449
450 // 定数レジスタ情報
451 struct SetupInfo
452 {
453 u16 type;
454 u16 index;
455 u32 value[4];
456 };
457
458 enum { TYPE_BOOL = 0, TYPE_INT = 1, TYPE_FLOAT = 2 };
459
460 const SetupInfo* setupInfoTable =
461 static_cast<const SetupInfo*>( ut::AddOffsetToPtr( exeInfo, exeInfo->setupOffset) );
462
463 // 定数レジスタのコマンド生成
464 for ( int i = 0; i < exeInfo->setupCount; ++i )
465 {
466 const SetupInfo& info = setupInfoTable[ i ];
467 const u32* value = info.value;
468
469 switch ( info.type )
470 {
471 case TYPE_BOOL:
472 break;
473
474 case TYPE_INT:
475 {
476 const u32 COMMAND[] =
477 {
478 value[ 0 ],
479 internal::MakeCommandHeader(regInteger + info.index, 1, false, 0xF)
480 };
481
482 buffer.Write( &COMMAND[0], sizeof(COMMAND) );
483 }
484 break;
485
486 case TYPE_FLOAT:
487
488 {
489 const u32 COMMAND[] =
490 {
491 info.index, // 24 bit モード
492 internal::MakeCommandHeader( regFloat, 4, true, 0xF ),
493 ( value[ 3 ] << 8 & 0xffffff00 ) | ( value[ 2 ] >> 16 & 0x000000ff ),
494 ( value[ 2 ] << 16 & 0xffff0000 ) | ( value[ 1 ] >> 8 & 0x0000ffff ),
495 ( value[ 1 ] << 24 & 0xff000000 ) | ( value[ 0 ] >> 0 & 0x00ffffff ),
496 0, // padding
497 };
498
499 buffer.Write( &COMMAND[0], sizeof(COMMAND) );
500 }
501 break;
502 }
503 }
504 }
505
506 //---------------------------------------------------------------------------
507 // NOTE: コマンドのサイズが変わる場合は、必ず GetOutAttrCommandSize も合わせて修正する。
508 void
BuildOutAttrCommand(SafeBuffer & buffer,s32 vertexIndex,s32 geometryIndex) const509 ShaderBinaryInfo::BuildOutAttrCommand( SafeBuffer& buffer, s32 vertexIndex, s32 geometryIndex ) const
510 {
511 bool hasGeometry = geometryIndex >= 0;
512
513 u32 vertexOutputMask;
514 u32 vertexOutputNum;
515 u32 shaderOutputMask;
516 u32 shaderOutputNum;
517 u32 shaderOutputMap[7];
518 u32 clockControl = 0x01030703; // クロック制御はひとまず全て有効。
519 u32 vertexEntry;
520 u32 geometryInputNum;
521 u32 geometryEntry;
522 bool isTextureOutput = false;
523
524 this->GetOutputRegisterNum( vertexIndex, &vertexOutputNum, &vertexOutputMask );
525 this->GetShaderOutputRegisterNum( vertexIndex, geometryIndex, &shaderOutputNum, &shaderOutputMask );
526 this->GetShaderOutputRegisterMap( vertexIndex, geometryIndex, &shaderOutputMap[0] );
527 vertexEntry = this->GetEntryAddress( vertexIndex );
528
529 u32 GEOMETRY_SETTING_COMMAND[] =
530 {
531 0x00000000, 0x000f0252,
532 0x00000000, 0x00010254,
533 0x00000000, 0x00080229,
534 0x00000000, 0x00020289,
535 };
536
537 if ( hasGeometry )
538 {
539 enum { IDX_REG_252 = 0, IDX_REG_254 = 2, IDX_REG_229 = 4, IDX_REG_289 = 6 };
540
541 geometryInputNum = vertexOutputNum;
542 geometryEntry = this->GetEntryAddress( geometryIndex );
543
544 u32 geometryMode = this->GetGeometryDataMode( geometryIndex );
545
546 GEOMETRY_SETTING_COMMAND[ IDX_REG_252 ] |= geometryMode & 0x3;
547
548 switch ( geometryMode )
549 {
550 case 0: // normal mode
551 break;
552 case 1: // subdivision mode
553 {
554 GEOMETRY_SETTING_COMMAND[ IDX_REG_229 ] |= 1u << 31;
555 GEOMETRY_SETTING_COMMAND[ IDX_REG_289 ] |= 1 << 8;
556
557 u32 geomMainVertexNum = this->GetGeometryMainVertexNum( geometryIndex );
558
559 GEOMETRY_SETTING_COMMAND[ IDX_REG_254 ] |= geomMainVertexNum;
560 }
561 break;
562 case 2: // constant data mode
563 {
564 GEOMETRY_SETTING_COMMAND[ IDX_REG_289 ] |= 1 << 8;
565
566 u32 geomPatchSize = this->GetGeometryPatchSize( geometryIndex );
567 u32 geomStartIndex = this->GetGeometryStartIndex( geometryIndex );
568
569 GEOMETRY_SETTING_COMMAND[ IDX_REG_252 ] |= (geomPatchSize - 1) << 8;
570 GEOMETRY_SETTING_COMMAND[ IDX_REG_252 ] |= (vertexOutputNum - 1) << 12;
571 GEOMETRY_SETTING_COMMAND[ IDX_REG_252 ] |= geomStartIndex << 16;
572 GEOMETRY_SETTING_COMMAND[ IDX_REG_252 ] |= 1 << 24;
573 }
574 break;
575 default:
576 NW_FATAL_ERROR("Invalid geometry mode");
577 }
578 }
579
580 // 頂点入出力レジスタ設定
581 const u32 SHADER_PROGRAM_COMMAND[] =
582 {
583 vertexOutputMask, 0x000f02bd, // 頂点出力マスク (vtx)
584 vertexOutputNum - 1, 0x000f0251, // 出力レジスタ数 - 1 (vtx)
585 vertexOutputNum - 1, 0x000f024a, // 出力レジスタ数 - 1 (vtx)
586 shaderOutputNum - 1, 0x0001025e, // 出力レジスタ数 - 1 (vtx/geom)
587 shaderOutputNum, 0x000f004f, // 出力レジスタ数 (vtx/geom)
588 shaderOutputMap[0], 0x806f0050, // 出力レジスタ0のフォーマット
589 shaderOutputMap[1], shaderOutputMap[2], // 出力レジスタ1,2のフォーマット
590 shaderOutputMap[3], shaderOutputMap[4], // 出力レジスタ3,4のフォーマット
591 shaderOutputMap[5], shaderOutputMap[6], // 出力レジスタ5,6のフォーマット
592 0x00000001, 0x000f0064, // テクスチャ座標が出力される場合は1
593 clockControl, 0x000f006f, // シェーダクロック制御
594 0x7fff0000 | vertexEntry, 0x000f02ba, // 頂点シェーダ開始アドレス
595 };
596
597 u32 geometrySettingCommandSize = sizeof(GEOMETRY_SETTING_COMMAND) - sizeof(u32) * (hasGeometry ? 0 : 2);
598 buffer.Write( &GEOMETRY_SETTING_COMMAND[0], geometrySettingCommandSize );
599 buffer.Write( &SHADER_PROGRAM_COMMAND[0], sizeof(SHADER_PROGRAM_COMMAND) );
600
601 if ( hasGeometry )
602 {
603 // ジオメトリ入出力レジスタ設定
604 const u32 GEOMETRY_COMMAND[] =
605 {
606 shaderOutputMask, 0x000f028d, // ジオメトリ出力マスク
607 0x08000000 | (geometryInputNum - 1), 0x00090289, // ジオメトリシェーダの入力レジスタ数 - 1
608 0x7fff0000 | geometryEntry, 0x000f028a, // ジオメトリシェーダの開始アドレス
609 };
610
611 buffer.Write( &GEOMETRY_COMMAND[0], sizeof(GEOMETRY_COMMAND) );
612 }
613 }
614
615 //---------------------------------------------------------------------------
616 void
PutEnableMirroringShaderSetting(SafeBuffer & buffer,bool enableMirroring) const617 ShaderBinaryInfo::PutEnableMirroringShaderSetting(SafeBuffer& buffer, bool enableMirroring) const
618 {
619 const u32 COMMAND[] =
620 {
621 enableMirroring ? 0 : 1,
622 internal::MakeCommandHeader( PICA_REG_VS_COM_MODE, 1, false, 0x1 )
623 };
624
625 buffer.Write( &COMMAND[0], sizeof(COMMAND) );
626 }
627
628 //---------------------------------------------------------------------------
629 // NOTE: コマンドのサイズが変わる場合は、必ず GetLoadCommandSize も合わせて修正する。
630 void
PutLoadCommand(SafeBuffer & buffer,u32 regAddr,const u32 * src,u32 count) const631 ShaderBinaryInfo::PutLoadCommand(
632 SafeBuffer& buffer,
633 u32 regAddr,
634 const u32* src,
635 u32 count
636 ) const
637 {
638 enum { WRITE_MAX = 128 };
639
640 u32 restCount = count;
641 u32 index = 0;
642
643 while ( true )
644 {
645 u32 countPerCommand = ut::Min( restCount, u32(WRITE_MAX) );
646
647 const u32 COMMAND[] =
648 {
649 src[index],
650 internal::MakeCommandHeader( regAddr, countPerCommand, false, 0xF )
651 };
652
653 buffer.Write( &COMMAND[0], sizeof(COMMAND) );
654 buffer.Write( &src[index + 1], (countPerCommand - 1) * sizeof(u32) );
655
656 if ( (countPerCommand % 2) == 0 )
657 {
658 buffer.Write( 0 ); // パディング挿入
659 }
660
661 index += countPerCommand;
662 restCount -= countPerCommand;
663
664 if (restCount == 0)
665 {
666 break;
667 }
668 }
669 }
670
671 //---------------------------------------------------------------------------
672 s32
GetLoadCommandSize(u32 count) const673 ShaderBinaryInfo::GetLoadCommandSize(u32 count) const
674 {
675 enum { WRITE_MAX = 128 };
676
677 s32 commandSize = 0;
678 u32 restCount = count;
679
680 while ( true )
681 {
682 u32 countPerCommand = ut::Min( restCount, u32(WRITE_MAX) );
683
684 commandSize += 2 * sizeof(u32);
685 commandSize += (countPerCommand - 1) * sizeof(u32);
686
687 if ( (countPerCommand % 2) == 0 )
688 {
689 commandSize += sizeof(u32);
690 }
691
692 restCount -= countPerCommand;
693
694 if (restCount == 0)
695 {
696 break;
697 }
698 }
699
700 return commandSize;
701 }
702
703
704 } // namespace gfx
705 } // namespace nw
706