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