1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_CommandUtil.h
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: 27965 $
14  *---------------------------------------------------------------------------*/
15 #ifndef NW_GFX_COMMAND_UTIL_H_
16 #define NW_GFX_COMMAND_UTIL_H_
17 
18 #include <nw/types.h>
19 #include <nw/ut/ut_Inlines.h>
20 #include <nw/gfx/gfx_GlImplement.h>
21 #include <nw/dev.h>
22 #include <nw/gfx/gfx_MemoryUtil.h>
23 
24 // #define NW_UNIFORM_DUMP
25 
26 #include <gles2/gl2.h>
27 #include <gles2/gl2ext.h>
28 #include <nn/gx.h>
29 #include <cstring>
30 
31 namespace nw {
32 namespace gfx {
33 
34 //---------------------------------------------------------------------------
35 //! @brief        コマンドキャッシュ動的生成用のバッファを確保する為のグローバルアロケータ設定です。
36 //---------------------------------------------------------------------------
37 class CommandCacheManager
38 {
39 public:
40     //---------------------------------------------------------------------------
41     //! @brief        コマンドキャッシュ確保用のアロケータを設定します。
42     //!
43     //! @param[out]   allocator コマンドキャッシュの確保に使用するアロケータです。
44     //---------------------------------------------------------------------------
SetAllocator(nw::os::IAllocator * allocator)45     static void SetAllocator(nw::os::IAllocator* allocator) { s_Allocator = allocator; }
46 
47     //---------------------------------------------------------------------------
48     //! @brief        設定されているアロケータを取得します。
49     //!
50     //! @return       CommandCacheManager に設定されているアロケータです。
51     //---------------------------------------------------------------------------
GetAllocator()52     static nw::os::IAllocator* GetAllocator() { return s_Allocator; }
53 
54     //---------------------------------------------------------------------------
55     //! @brief        コマンドキャッシュ生成用にアロケートをおこないます。
56     //!
57     //! @param[in]    size    確保するメモリサイズです。
58     //!
59     //! @return       アロケートしたメモリ領域を返します。
60     //---------------------------------------------------------------------------
Allocate(s32 size)61     static void* Allocate(s32 size)
62     {
63         NW_NULL_ASSERT( s_Allocator );
64         return s_Allocator->Alloc(size, 4);
65     }
66 
67     //---------------------------------------------------------------------------
68     //! @brief        メモリ領域を開放をおこないます。
69     //!
70     //! @param[out]   buffer  解放をおこなうメモリ領域です。
71     //---------------------------------------------------------------------------
Free(void * buffer)72     static void Free(void* buffer)
73     {
74         if (s_Allocator != NULL )
75         {
76             s_Allocator->Free(buffer);
77         }
78         else
79         {
80             NW_WARNING(false, "No allocator available");
81         }
82     }
83 
84 private:
85     static nw::os::IAllocator* s_Allocator;
86 };
87 
88 namespace internal {
89 
90 
91 //---------------------------------------------------------------------------
92 //! @brief        コマンドキャッシュのコマンドヘッダアクセスクラスです。
93 //---------------------------------------------------------------------------
94 class CommandHeader
95 {
96 public:
97     //---------------------------------------------------------------------------
98     //! @brief        コンストラクタです。
99     //!
100     //! @param[in]    rawData ヘッダの64bit値です。
101     //---------------------------------------------------------------------------
CommandHeader(u64 rawData)102     CommandHeader(u64 rawData) : m_RawData( rawData >> 32 ) {}
103 
104     //---------------------------------------------------------------------------
105     //! @brief        コンストラクタです。
106     //!
107     //! @param[in]    rawData ヘッダの32bit値です。
108     //!           Little Endian では 2ワード目を与える必要があるのに注意。
109     //---------------------------------------------------------------------------
CommandHeader(u32 rawData)110     CommandHeader(u32 rawData) : m_RawData( rawData ) {}
111 
112     //---------------------------------------------------------------------------
113     //! @brief        レジスタアドレスを取得します。
114     //!
115     //! @return       レジスタアドレスです。
116     //---------------------------------------------------------------------------
GetAddress()117     u32 GetAddress() const
118     {
119         return (this->m_RawData & ADDRESS_MASK);
120     }
121 
122     //---------------------------------------------------------------------------
123     //! @brief        書き込みデータ数を取得します。
124     //!
125     //! @return       書き込みをおこなうu32データの数です。
126     //---------------------------------------------------------------------------
GetSize()127     s32 GetSize() const
128     {
129         return ((this->m_RawData & SIZE_MASK) >> SIZE_SHIFT) + 1;
130     }
131 
132     //---------------------------------------------------------------------------
133     //! @brief        バイトイネーブルの設定値を取得します。
134     //!
135     //! @return       バイトイネーブルの設定値です。
136     //---------------------------------------------------------------------------
GetByteEnable()137     u8 GetByteEnable() const
138     {
139         return static_cast<u8>((this->m_RawData & BYTE_ENABLE_MASK) >> BYTE_ENABLE_SHIFT);
140     }
141 
142     //---------------------------------------------------------------------------
143     //! @brief        バイトイネーブルから生成されるマスクを取得します。
144     //!
145     //! @return       バイトイネーブルから生成されるマスクです。
146     //---------------------------------------------------------------------------
GetByteEnableMask()147     u32 GetByteEnableMask() const
148     {
149         u8 be = this->GetByteEnable();
150         u32 mask = 0;
151 
152         mask |= (be & 0x1) ? 0x000000FF : 0;
153         mask |= (be & 0x2) ? 0x0000FF00 : 0;
154         mask |= (be & 0x4) ? 0x00FF0000 : 0;
155         mask |= (be & 0x8) ? 0xFF000000 : 0;
156         return mask;
157     }
158 
159     //---------------------------------------------------------------------------
160     //! @brief        連続書き込みモードのフラグを取得します。
161     //!
162     //! @return       連続アドレス書き込みモードは 1 、
163     //!               単一書き込みモードは 0 を返します。
164     //---------------------------------------------------------------------------
GetBurstModeFlag()165     u32 GetBurstModeFlag() const
166     {
167         return this->m_RawData & BURST_FLAG;
168     }
169 
170 private:
171 
172     enum
173     {
174         ADDRESS_SHIFT = 0,
175         ADDRESS_WIDTH = 16,
176         ADDRESS_MASK  = 0xFFFF,
177         BYTE_ENABLE_SHIFT = 16,
178         BYTE_ENABLE_WIDTH = 4,
179         BYTE_ENABLE_MASK  = 0xF0000,
180         SIZE_SHIFT = 20,
181         SIZE_WIDTH = 8,
182         SIZE_MASK  = 0x0FF00000,
183         BURST_FLAG = 0x80000000
184     };
185 
186     //---------------------------------------------------------------------------
187     //! @brief        デフォルトコンストラクタは非公開にしています。
188     //---------------------------------------------------------------------------
CommandHeader()189     CommandHeader() {}
190 
191     u32 m_RawData;
192 };
193 
194 //---------------------------------------------------------------------------
195 //! @brief        レジスタの値とシフト、マスク設定から特定のビット位置の値を取得ます。
196 //!               mask 引数には shift がかかっていない 0 ビット目基準のマスク値を設定します。
197 //!
198 //! @param[in]    value   レジスタの値です。
199 //! @param[in]    mask    shift がかかっていないマスク設定です。
200 //! @param[in]    shift   取り出す値のシフト値です。
201 //!
202 //! @return       shift と mask 設定から取り出された値を取得します。
203 //---------------------------------------------------------------------------
204 inline u32
GetCmdValue(u32 value,u32 mask,s32 shift)205 GetCmdValue(u32 value, u32 mask, s32 shift)
206 {
207     return (value >> shift) & mask;
208 }
209 
210 template <typename TValue>
211 inline void
SetCmdValue(u32 * addr,TValue value,u32 mask,s32 shift)212 SetCmdValue(u32* addr, TValue value, u32 mask, s32 shift)
213 {
214     u32 result = *addr & ~(mask << shift);
215     *addr = result | ((static_cast<u32>(value) & static_cast<u32>(mask)) << shift);
216 }
217 
218 //---------------------------------------------------------------------------
219 //! @brief        Glの管理オブジェクトを設定します。
220 //---------------------------------------------------------------------------
221 class GlSystem
222 {
223 public:
224     //! @details :private
SetGlManagers(void *)225     static void SetGlManagers(void*) {}
226 
227     //! @details :private
SetGlVbManager(void *)228     static void SetGlVbManager(void*) {}
229 
230     //! @details :private
SetGlTexManager(void *)231     static void SetGlTexManager(void*) {}
232 
233     //---------------------------------------------------------------------------
234     //! @brief        頂点バッファアドレスを取得します。
235     //!
236     //! @param[in]    bufferId  vbo のIDです。
237     //---------------------------------------------------------------------------
238     static void*
GetBufferAddress(u32 bufferId)239     GetBufferAddress(u32 bufferId)
240     {
241         s32 addr;
242         glBindBuffer(GL_ARRAY_BUFFER, bufferId);
243         glGetBufferParameteriv(GL_ARRAY_BUFFER,  GL_BUFFER_DATA_ADDR_DMP, &addr);
244         NW_GL_ASSERT();
245 
246         return reinterpret_cast<void*>( addr );
247     }
248 
249     //---------------------------------------------------------------------------
250     //! @brief        頂点インデックスバッファアドレスを取得します。
251     //!
252     //! @param[in]    bufferId  vbo のIDです。
253     //---------------------------------------------------------------------------
254     static void*
GetElementBufferAddress(u32 bufferId)255     GetElementBufferAddress(u32 bufferId)
256     {
257         s32 addr;
258         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferId);
259         glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER,  GL_BUFFER_DATA_ADDR_DMP, &addr);
260         NW_GL_ASSERT();
261 
262         return reinterpret_cast<void*>( addr );
263     }
264 
265     //---------------------------------------------------------------------------
266     //! @brief        テクスチャアドレスを取得します。
267     //!
268     //! @param[in]    texId   テクスチャIDです。
269     //---------------------------------------------------------------------------
270     static void*
GetTextureAddress(u32 texId)271     GetTextureAddress(u32 texId)
272     {
273         s32 addr;
274 
275         glBindTexture( GL_TEXTURE_2D, texId );
276         glGetTexParameteriv( GL_TEXTURE_2D, GL_TEXTURE_DATA_ADDR_DMP, &addr );
277 
278         NW_GL_ASSERT();
279         return reinterpret_cast<void*>(addr);
280     }
281 
282     //---------------------------------------------------------------------------
283     //! @brief        キューブテクスチャのアドレスを取得します。
284     //!
285     //! @param[in]    texId   テクスチャIDです。
286     //! @param[in]    face    キューブ面のIDです。
287     //---------------------------------------------------------------------------
288     static void*
GetCubeTextureAddress(u32 texId,int face)289     GetCubeTextureAddress(u32 texId, int face)
290     {
291         s32 addr[6];
292 
293         glBindTexture( GL_TEXTURE_CUBE_MAP, texId );
294         glGetTexParameteriv( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_DATA_ADDR_DMP, &addr[0] );
295         NW_GL_ASSERT();
296 
297         return reinterpret_cast<void*>(addr[face]);
298     }
299 };
300 
301 //---------------------------------------------------------------------------
302 //! @brief        直接バッファを渡せる版が無いので強引に対応。
303 //!
304 //! @param[out]   buffer  コマンドのはいったバッファのアドレス。
305 //! @param[in]    size    バッファサイズ。
306 //---------------------------------------------------------------------------
307 template <typename T>
308 NW_FORCE_INLINE void
NWUseCmdlist(const T * buffer,int size)309 NWUseCmdlist(const T* buffer, int size)
310 {
311 #if 0 // SDK の更新で nngxAdd3DCommand の 8byte アライン制限が無くなったらこちらを有効にする。
312     nngxAdd3DCommand( const_cast<GLvoid*>(buffer), GLsizei(size), GL_TRUE );
313 #else
314     NW_ASSERT(size > 0);
315     NW_ALIGN_ASSERT(size, 4);
316     NW_NULL_ASSERT( buffer );
317 
318     nw::os::MemCpy(__cb_current_command_buffer, buffer, size);
319     __cb_current_command_buffer += size >> 2;
320 #endif
321 }
322 
323 template <int size>
324 NW_FORCE_INLINE void
NWUseCmdlist(const void * buffer)325 NWUseCmdlist(const void* buffer)
326 {
327     NW_ASSERT(size > 0);
328     NW_ALIGN_ASSERT(size, 4);
329     NW_NULL_ASSERT( buffer );
330 
331 #if 1
332     __cb_current_command_buffer =
333         internal::FastWordCopy((u32*)__cb_current_command_buffer, (u32*)buffer, size);
334 #else
335     nw::os::MemCpy(__cb_current_command_buffer, buffer, size);
336     __cb_current_command_buffer += size >> 2;
337 #endif
338 }
339 
340 template <>
341 NW_FORCE_INLINE void
342 NWUseCmdlist<4>(const void* buffer)
343 {
344     NW_NULL_ASSERT( buffer );
345 
346     *reinterpret_cast<u32*>(__cb_current_command_buffer) = *reinterpret_cast<const u32*>(buffer);
347     __cb_current_command_buffer += 1;
348 }
349 
350 template <>
351 NW_FORCE_INLINE void
352 NWUseCmdlist<8>(const void* buffer)
353 {
354     NW_NULL_ASSERT( buffer );
355 
356     *reinterpret_cast<u64*>(__cb_current_command_buffer) = *reinterpret_cast<const u64*>(buffer);
357     __cb_current_command_buffer += 2;
358 }
359 
360 template <>
361 NW_FORCE_INLINE void
362 NWUseCmdlist<12>(const void* buffer)
363 {
364     NW_NULL_ASSERT( buffer );
365 
366     *reinterpret_cast<u64*>(__cb_current_command_buffer) = *reinterpret_cast<const u64*>(buffer);
367     *reinterpret_cast<u32*>(__cb_current_command_buffer + 2) = *(reinterpret_cast<const u32*>(buffer) + 2);
368     __cb_current_command_buffer += 3;
369 }
370 
371 template <>
372 NW_FORCE_INLINE void
373 NWUseCmdlist<16>(const void* buffer)
374 {
375     NW_NULL_ASSERT( buffer );
376 
377     *reinterpret_cast<u64*>(__cb_current_command_buffer) = *reinterpret_cast<const u64*>(buffer);
378     *reinterpret_cast<u64*>(__cb_current_command_buffer + 2) = *(reinterpret_cast<const u64*>(buffer) + 1);
379     __cb_current_command_buffer += 4;
380 }
381 
382 
383 //---------------------------------------------------------------------------
384 //! @brief        カレントのコマンドリストの、書き込み位置を取得します。
385 //!
386 //! @return       カレントコマンドリストの書き込み位置です。
387 //---------------------------------------------------------------------------
388 NW_FORCE_INLINE void*
NWGetCurrentCmdBuffer()389 NWGetCurrentCmdBuffer()
390 {
391     return __cb_current_command_buffer;
392 }
393 
394 
395 //---------------------------------------------------------------------------
396 //! @brief        アクティブなコマンドバッファの末尾を取得します。
397 //!
398 //! @return       コマンドバッファの末尾ポインタです。
399 //---------------------------------------------------------------------------
400 NW_FORCE_INLINE void*
NWGetCmdBufferEnd()401 NWGetCmdBufferEnd()
402 {
403     return __cb_current_max_command_buffer;
404 }
405 
406 //---------------------------------------------------------------------------
407 //! @brief        カレントのコマンドリストの、書き込み位置を前に進めます。
408 //!
409 //! @param[in]    size    カレントのポイントを進めるバイト数です。
410 //---------------------------------------------------------------------------
411 NW_FORCE_INLINE void
NWForwardCurrentCmdBuffer(u32 size)412 NWForwardCurrentCmdBuffer(u32 size)
413 {
414     NW_ALIGN_ASSERT(size, 4);
415 
416     __cb_current_command_buffer += size >> 2;
417 }
418 
419 
420 //---------------------------------------------------------------------------
421 //! @brief        カレントのコマンドリストの、書き込み位置を前に進めます。
422 //!
423 //! @param[in]    size    カレントのポイントを進めるバイト数です。
424 //---------------------------------------------------------------------------
425 NW_FORCE_INLINE void
NWBackwardCurrentCmdBuffer(u32 size)426 NWBackwardCurrentCmdBuffer(u32 size)
427 {
428     NW_ALIGN_ASSERT(size, 4);
429 
430     __cb_current_command_buffer -= size >> 2;
431 }
432 
433 //---------------------------------------------------------------------------
434 //! @brief        コマンドヘッダを生成します。
435 //!
436 //! @param[in]    address  レジスタアドレスです。
437 //! @param[in]    count    書き込みデータ数です。
438 //! @param[in]    incremental 連続アドレスモードかどうかのフラグです。
439 //! @param[in]    byteEnable  バイトイネーブルマスクです。
440 //!
441 //! @return       生成されたコマンドヘッダを返します。
442 //
443 // |seq:1|rsv:3|size:8|be:4|addr:16|
444 //
445 // seq: 0 の場合単一レジスタ書き込み。 1 の場合は連続レジスタ書き込み。
446 // rsv: 予約。
447 // size: 32bitデータの個数 - 1。
448 // be: 32bit データへのバイト単位のマスク。
449 // addr: 書き込み先アドレス。
450 //---------------------------------------------------------------------------
451 NW_INLINE u32
MakeCommandHeader(u32 address,int count,bool incremental,u8 byteEnable)452 MakeCommandHeader(u32 address, int count, bool incremental, u8 byteEnable)
453 {
454     enum
455     {
456         ADDRESS_SHIFT     = 0,
457         ADDRESS_WIDTH     = 16,
458         BYTE_ENABLE_SHIFT = 16,
459         BYTE_ENABLE_WIDTH = 4,
460         SIZE_SHIFT        = 20,
461         SIZE_WIDTH        = 8,
462         BURST_MODE_SHIFT  = 31
463     };
464 
465     NW_ASSERT(0 < count && count <= 256);
466 
467     u32 result = 0;
468 
469     if (incremental)
470     {
471         result |= (0x1U << BURST_MODE_SHIFT);
472     }
473 
474     result |= ut::internal::MakeBits(count - 1, SIZE_WIDTH, SIZE_SHIFT);
475     result |= ut::internal::MakeBits(address, ADDRESS_WIDTH, ADDRESS_SHIFT);
476     result |= ut::internal::MakeBits(byteEnable, BYTE_ENABLE_WIDTH, BYTE_ENABLE_SHIFT);
477 
478     return result;
479 }
480 
481 #define NW_GFX_GPU_HEADER(addr, count, incremental, byteEnable)  (u32)((incremental << 31) | (count << 20) | (byteEnable << 16) | address)
482 
483 
484 enum UniformRegistry
485 {
486     REG_VERTEX_UNIFORM_FLOAT_INDEX = 0x2C0,
487     REG_VERTEX_UNIFORM_FLOAT_BASE = 0x2C1,
488     REG_GEOMETRY_UNIFORM_FLOAT_INDEX = 0x290,
489     REG_GEOMETRY_UNIFORM_FLOAT_BASE = 0x291
490 };
491 
492 //---------------------------------------------------------------------------
493 //! @brief        VEC4をwzyxの順に逆転してコピーします。
494 //---------------------------------------------------------------------------
495 void NWCopyVec4Reverse(f32* dst, const f32*  src);
496 
497 //---------------------------------------------------------------------------
498 //! @brief        VEC4をwzyxの順に逆転してヘッダと共にコピーします。
499 //---------------------------------------------------------------------------
500 void NWCopyVec4WithHeader(f32* dst, const f32* src, u32 header);
501 
502 //---------------------------------------------------------------------------
503 //! @brief        Matrix2x4をwzyxの順に逆転してコピーします。
504 //---------------------------------------------------------------------------
505 void NWCopyMtx24Reverse(f32* dst, const f32* src);
506 
507 //---------------------------------------------------------------------------
508 //! @brief        Matrix2x4をwzyxの順に逆転してヘッダと共にコピーします。
509 //---------------------------------------------------------------------------
510 void NWCopyMtx24WithHeader(f32* dst, const f32* src, u32 header);
511 
512 //---------------------------------------------------------------------------
513 //! @brief        Matrix3x4をwzyxの順に逆転してコピーします。
514 //---------------------------------------------------------------------------
515 void NWCopyMtx34Reverse(f32* dst, const f32* src);
516 
517 //---------------------------------------------------------------------------
518 //! @brief        Matrix3x4をwzyxの順に逆転してヘッダと共にコピーします。
519 //---------------------------------------------------------------------------
520 void NWCopyMtx34WithHeader(f32* dst, const f32* src, u32 header);
521 
522 //---------------------------------------------------------------------------
523 //! @brief        Matrix4x4をwzyxの順に逆転してコピーします。
524 //---------------------------------------------------------------------------
525 void NWCopyMtx44Reverse(f32* dst, const f32* src);
526 
527 //---------------------------------------------------------------------------
528 //! @brief        Matrix4x4をwzyxの順に逆転してヘッダと共にコピーします。
529 //---------------------------------------------------------------------------
530 void NWCopyMtx44WithHeader(f32*  dst, const f32* src, u32 header);
531 
532 //---------------------------------------------------------------------------
533 //! @brief        VEC3をwzyxの順に逆転してコピーします。
534 //---------------------------------------------------------------------------
535 void NWCopyVec3Reverse(f32* dst, const f32* src);
536 
537 //---------------------------------------------------------------------------
538 //! @brief        VEC3をwzyxの順に逆転してヘッダと共にコピーします。
539 //---------------------------------------------------------------------------
540 void NWCopyVec3WithHeader(f32* dst, const f32* src, u32 header );
541 
542 //---------------------------------------------------------------------------
543 //! @brief        Matrix2x3をwzyxの順に逆転してコピーします。
544 //---------------------------------------------------------------------------
545 void NWCopyMtx23Reverse(f32* dst, const f32* src);
546 
547 //---------------------------------------------------------------------------
548 //! @brief        Matrix2x3をwzyxの順に逆転してヘッダと共にコピーします。
549 //---------------------------------------------------------------------------
550 void NWCopyMtx23WithHeader(f32* dst, const f32* src, u32 header );
551 
552 //---------------------------------------------------------------------------
553 //! @brief        Matrix3x3をwzyxの順に逆転してコピーします。
554 //---------------------------------------------------------------------------
555 void NWCopyMtx33Reverse(f32* dst, const f32* src);
556 
557 //---------------------------------------------------------------------------
558 //! @brief        Matrix3x3をwzyxの順に逆転してヘッダと共にコピーします。
559 //---------------------------------------------------------------------------
560 void NWCopyMtx33WithHeader(f32* dst, const f32* src, u32 header );
561 
562 //---------------------------------------------------------------------------
563 //! @brief        Matrix4x3をwzyxの順に逆転してコピーします。
564 //---------------------------------------------------------------------------
565 void NWCopyMtx43Reverse(f32* dst, const f32* src);
566 
567 //---------------------------------------------------------------------------
568 //! @brief        Matrix4x3をwzyxの順に逆転してヘッダと共にコピーします。
569 //---------------------------------------------------------------------------
570 void NWCopyMtx43WithHeader(f32* dst, const f32* src, u32 header );
571 
572 //---------------------------------------------------------------------------
573 //! @brief        VEC2をwzyxの順に逆転してコピーします。
574 //---------------------------------------------------------------------------
575 void NWCopyVec2Reverse(f32* dst, const f32* src);
576 
577 //---------------------------------------------------------------------------
578 //! @brief        VEC2をwzyxの順に逆転してヘッダと共にコピーします。
579 //---------------------------------------------------------------------------
580 void NWCopyVec2WithHeader(f32* dst, const f32* src, u32 header );
581 
582 //---------------------------------------------------------------------------
583 //! @brief        Matrix2x2をwzyxの順に逆転してコピーします。
584 //---------------------------------------------------------------------------
585 void NWCopyMtx22Reverse(f32* dst, const f32* src);
586 
587 //---------------------------------------------------------------------------
588 //! @brief        Matrix2x2をwzyxの順に逆転してヘッダと共にコピーします。
589 //---------------------------------------------------------------------------
590 void NWCopyMtx22WithHeader(f32* dst, const f32* src, u32 header );
591 
592 //---------------------------------------------------------------------------
593 //! @brief        Matrix3x2をwzyxの順に逆転してコピーします。
594 //---------------------------------------------------------------------------
595 void NWCopyMtx32Reverse(f32* dst, const f32* src);
596 
597 //---------------------------------------------------------------------------
598 //! @brief        Matrix3x2をwzyxの順に逆転してヘッダと共にコピーします。
599 //---------------------------------------------------------------------------
600 void NWCopyMtx32WithHeader(f32* dst, const f32* src, u32 header );
601 
602 //---------------------------------------------------------------------------
603 //! @brief        Matrix4x2をwzyxの順に逆転してコピーします。
604 //---------------------------------------------------------------------------
605 void NWCopyMtx42Reverse(f32* dst, const f32* src);
606 
607 //---------------------------------------------------------------------------
608 //! @brief        Matrix4x2をwzyxの順に逆転してヘッダと共にコピーします。
609 //---------------------------------------------------------------------------
610 void NWCopyMtx42WithHeader(f32* dst, const f32* src, u32 header );
611 
612 //---------------------------------------------------------------------------
613 //! @brief        VEC1をwzyxの順に逆転してコピーします。
614 //---------------------------------------------------------------------------
615 void NWCopyVec1Reverse(f32* dst, const f32* src);
616 
617 //---------------------------------------------------------------------------
618 //! @brief        VEC1をwzyxの順に逆転してヘッダと共にコピーします。
619 //---------------------------------------------------------------------------
620 void NWCopyVec1WithHeader(f32* dst, const f32* src, u32 header );
621 
622 //---------------------------------------------------------------------------
623 //! @brief        Matrix2x1をwzyxの順に逆転してコピーします。
624 //---------------------------------------------------------------------------
625 void NWCopyMtx21Reverse(f32* dst, const f32* src);
626 
627 //---------------------------------------------------------------------------
628 //! @brief        Matrix2x1をwzyxの順に逆転してヘッダと共にコピーします。
629 //---------------------------------------------------------------------------
630 void NWCopyMtx21WithHeader(f32* dst, const f32* src, u32 header );
631 
632 //---------------------------------------------------------------------------
633 //! @brief        Matrix3x1をwzyxの順に逆転してコピーします。
634 //---------------------------------------------------------------------------
635 void NWCopyMtx31Reverse(f32* dst, const f32* src);
636 
637 //---------------------------------------------------------------------------
638 //! @brief        Matrix3x1をwzyxの順に逆転してヘッダと共にコピーします。
639 //---------------------------------------------------------------------------
640 void NWCopyMtx31WithHeader(f32* dst, const f32* src, u32 header );
641 
642 //---------------------------------------------------------------------------
643 //! @brief        Matrix4x1をwzyxの順に逆転してコピーします。
644 //---------------------------------------------------------------------------
645 void NWCopyMtx41Reverse(f32* dst, const f32* src);
646 
647 //---------------------------------------------------------------------------
648 //! @brief        Matrix4x1をwzyxの順に逆転してヘッダと共にコピーします。
649 //---------------------------------------------------------------------------
650 void NWCopyMtx41WithHeader(f32* dst, const f32* src, u32 header );
651 
652 //---------------------------------------------------------------------------
653 //! @brief        ユニフォーム値をGPUへ送信します。
654 //!
655 //! @param[in]    index   シェーダユニフォームのインデクスです。
656 //! @param[in]    count   設定するユニフォーム数です。
657 //! @param[in]    data    設定データ列の先頭アドレスです。
658 //---------------------------------------------------------------------------
659 template <u32 RegFloatIndex>
660 NW_FORCE_INLINE void
NWSetUniform4fv(u32 index,int count,const f32 * data)661 NWSetUniform4fv(u32 index, int count, const f32* data)
662 {
663 #if defined(NW_UNIFORM_DUMP)
664     NW_LOG("Set Uniform 4fv: %d\n", index);
665 #endif
666 
667     enum
668     {
669         REG_UNIFORM_FLOAT_INDEX = RegFloatIndex,
670         REG_UNIFORM_FLOAT_BASE  = REG_UNIFORM_FLOAT_INDEX + 1,
671         SIZE_SHIFT = 20,
672         VECTOR4 = 1,
673         MATRIX2x4 = 2,
674         MATRIX3x4 = 3,
675         MATRIX4x4 = 4,
676         REG_COUNT = 4
677     };
678 
679      // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。
680     NW_MINMAX_ASSERT(count, 1, 64);
681     NW_NULL_ASSERT( data );
682     NW_MINMAX_ASSERT(index, 0, 96);
683 
684     const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF);
685 
686     // レジスタが2本以下の場合は、1コマンドで送信可能。
687     const u32 SHORT_HEADER[2] =
688     {
689         0x80000000 + index,
690         SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT)
691     };
692 
693     // レジスタが2本以下の場合は、1コマンドで送信可能。
694     const u32 SHORT_HEADER2[2] =
695     {
696         0x80000000 + index,
697         SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT)
698     };
699 
700     // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。
701     const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF);
702     const u32 LONG_VALUE_HEADER   = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF);
703 
704     const u32 LONG_HEADER[2] =
705     {
706         0x80000000 + index,
707         LONG_ADDRESS_HEADER
708     };
709 
710     u32* command = (u32*)NWGetCurrentCmdBuffer();
711 
712     switch (count)
713     {
714         case VECTOR4:
715         {
716             command[0] = SHORT_HEADER[0];
717             command[1] = SHORT_HEADER[1];
718             NWCopyVec4Reverse(reinterpret_cast<f32*>(&command[2]), data);
719             // アドレスヘッダで2Word進める
720             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT );
721 
722             //NWUseCmdlist(data, sizeof(f32) * REG_COUNT);
723             break;
724         }
725         case MATRIX2x4:
726         {
727             command[0] = SHORT_HEADER2[0];
728             command[1] = SHORT_HEADER2[1];
729             NWCopyMtx24Reverse(reinterpret_cast<f32*>(&command[2]), data);
730             // アドレスヘッダで2Word進める
731             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x4 );
732 
733             //NWUseCmdlist(data, sizeof(f32) * REG_COUNT * MATRIX2x4);
734             break;
735         }
736         case MATRIX3x4:
737         {
738             command[0] = LONG_HEADER[0];
739             command[1] = LONG_HEADER[1];
740             NWCopyMtx34WithHeader(
741                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x4 * REG_COUNT - 1) << SIZE_SHIFT));
742             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
743             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x4) * sizeof(f32) );
744 
745             //const u32 HEADER[4] =
746             //{
747             //    0x80000000 + index,
748             //    ADDRESS_HEADER,
749             //    *reinterpret_cast<const u32*>(&data[0]),
750             //    VALUE_HEADER | ((count * 4 - 1) << SIZE_SHIFT)
751             //};
752 
753             //NWUseCmdlist(HEADER, sizeof(u32) * 4);
754             //NWUseCmdlist(&data[1], sizeof(f32) * (REG_COUNT * MATRIX3x4 - 1));
755 
756             // 64bit 境界にパディング
757             //NWUseCmdlist(&PADDING[0], sizeof(f32));
758             break;
759         }
760         case MATRIX4x4:
761         {
762             command[0] = LONG_HEADER[0];
763             command[1] = LONG_HEADER[1];
764             NWCopyMtx44WithHeader(
765                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x4 * REG_COUNT - 1) << SIZE_SHIFT));
766             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
767             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x4) * sizeof(f32) );
768 
769             //const u32 HEADER[4] =
770             //{
771             //    0x80000000 + index,
772             //    ADDRESS_HEADER,
773             //    *reinterpret_cast<const u32*>(&data[0]),
774             //    VALUE_HEADER | ((count * 4 - 1) << SIZE_SHIFT)
775             //};
776 
777             //NWUseCmdlist(HEADER, sizeof(u32) * REG_COUNT);
778             //NWUseCmdlist(&data[1], sizeof(f32) * (REG_COUNT * MATRIX4x4 - 1));
779 
780             // 64bit 境界にパディング
781             //NWUseCmdlist(&PADDING[0], sizeof(f32));
782             break;
783         }
784         default:
785         {
786             NW_FATAL_ERROR("Not supported yet.\n");
787             break;
788         }
789     }
790 }
791 
792 //---------------------------------------------------------------------------
793 //! @brief        ユニフォーム値をGPUへ送信します。
794 //!
795 //! @param[in]    index   シェーダユニフォームのインデクスです。
796 //! @param[in]    count   設定するユニフォーム数です。
797 //! @param[in]    data    設定データ列の先頭アドレスです。
798 //---------------------------------------------------------------------------
799 template <u32 RegFloatIndex>
800 NW_FORCE_INLINE void
NWSetUniform3fv(u32 index,int count,const f32 * data)801 NWSetUniform3fv(u32 index, int count, const f32* data)
802 {
803 #if defined(NW_UNIFORM_DUMP)
804     NW_LOG("Set Uniform 3fv: %d\n", index);
805 #endif
806 
807     enum
808     {
809         REG_UNIFORM_FLOAT_INDEX = RegFloatIndex,
810         REG_UNIFORM_FLOAT_BASE  = REG_UNIFORM_FLOAT_INDEX + 1,
811         SIZE_SHIFT = 20,
812         VECTOR3 = 1,
813         MATRIX2x3 = 2,
814         MATRIX3x3 = 3,
815         MATRIX4x3 = 4,
816         // データの存在しない領域には 0.0f を設定するのでレジスタは常に4。
817         REG_COUNT = 4
818     };
819 
820      // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。
821     NW_MINMAX_ASSERT(count, 1, 64);
822     NW_NULL_ASSERT( data );
823     NW_MINMAX_ASSERT(index, 0, 96);
824 
825     const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF);
826 
827     // レジスタが2本以下の場合は、1コマンドで送信可能。
828     const u32 SHORT_HEADER[2] =
829     {
830         0x80000000 + index,
831         SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT)
832     };
833 
834     // レジスタが2本以下の場合は、1コマンドで送信可能。
835     const u32 SHORT_HEADER2[2] =
836     {
837         0x80000000 + index,
838         SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT)
839     };
840 
841     // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。
842     const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF);
843     const u32 LONG_VALUE_HEADER   = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF);
844 
845     const u32 LONG_HEADER[2] =
846     {
847         0x80000000 + index,
848         LONG_ADDRESS_HEADER
849     };
850 
851     u32* command = (u32*)NWGetCurrentCmdBuffer();
852 
853     switch (count)
854     {
855         case VECTOR3:
856         {
857             command[0] = SHORT_HEADER[0];
858             command[1] = SHORT_HEADER[1];
859             NWCopyVec3Reverse(reinterpret_cast<f32*>(&command[2]), data);
860             // アドレスヘッダで2Word進める
861             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT );
862             break;
863         }
864         case MATRIX2x3:
865         {
866             command[0] = SHORT_HEADER2[0];
867             command[1] = SHORT_HEADER2[1];
868             NWCopyMtx23Reverse(reinterpret_cast<f32*>(&command[2]), data);
869             // アドレスヘッダで2Word進める
870             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x3 );
871             break;
872         }
873         case MATRIX3x3:
874         {
875             command[0] = LONG_HEADER[0];
876             command[1] = LONG_HEADER[1];
877             NWCopyMtx33WithHeader(
878                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x3 * REG_COUNT - 1) << SIZE_SHIFT));
879             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
880             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x3) * sizeof(f32) );
881             break;
882         }
883         case MATRIX4x3:
884         {
885             command[0] = LONG_HEADER[0];
886             command[1] = LONG_HEADER[1];
887             NWCopyMtx43WithHeader(
888                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x3 * REG_COUNT - 1) << SIZE_SHIFT));
889             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
890             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x3) * sizeof(f32) );
891             break;
892         }
893         default:
894         {
895             NW_FATAL_ERROR("Not supported yet.\n");
896             break;
897         }
898     }
899 }
900 
901 //---------------------------------------------------------------------------
902 //! @brief        ユニフォーム値をGPUへ送信します。
903 //!
904 //! @param[in]    index   シェーダユニフォームのインデクスです。
905 //! @param[in]    count   設定するユニフォーム数です。
906 //! @param[in]    data    設定データ列の先頭アドレスです。
907 //---------------------------------------------------------------------------
908 template <u32 RegFloatIndex>
909 NW_FORCE_INLINE void
NWSetUniform2fv(u32 index,int count,const f32 * data)910 NWSetUniform2fv(u32 index, int count, const f32* data)
911 {
912 #if defined(NW_UNIFORM_DUMP)
913     NW_LOG("Set Uniform 2fv: %d\n", index);
914 #endif
915 
916     enum
917     {
918         REG_UNIFORM_FLOAT_INDEX = RegFloatIndex,
919         REG_UNIFORM_FLOAT_BASE  = REG_UNIFORM_FLOAT_INDEX + 1,
920         SIZE_SHIFT = 20,
921         VECTOR2 = 1,
922         MATRIX2x2 = 2,
923         MATRIX3x2 = 3,
924         MATRIX4x2 = 4,
925         // データの存在しない領域には 0.0f を設定するのでレジスタは常に4。
926         REG_COUNT = 4
927     };
928 
929      // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。
930     NW_MINMAX_ASSERT(count, 1, 64);
931     NW_NULL_ASSERT( data );
932     NW_MINMAX_ASSERT(index, 0, 96);
933 
934     const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF);
935 
936     // レジスタが2本以下の場合は、1コマンドで送信可能。
937     const u32 SHORT_HEADER[2] =
938     {
939         0x80000000 + index,
940         SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT)
941     };
942 
943     // レジスタが2本以下の場合は、1コマンドで送信可能。
944     const u32 SHORT_HEADER2[2] =
945     {
946         0x80000000 + index,
947         SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT)
948     };
949 
950     // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。
951     const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF);
952     const u32 LONG_VALUE_HEADER   = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF);
953 
954     const u32 LONG_HEADER[2] =
955     {
956         0x80000000 + index,
957         LONG_ADDRESS_HEADER
958     };
959 
960     u32* command = (u32*)NWGetCurrentCmdBuffer();
961 
962     switch (count)
963     {
964         case VECTOR2:
965         {
966             command[0] = SHORT_HEADER[0];
967             command[1] = SHORT_HEADER[1];
968             NWCopyVec2Reverse(reinterpret_cast<f32*>(&command[2]), data);
969             // アドレスヘッダで2Word進める
970             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT );
971             break;
972         }
973         case MATRIX2x2:
974         {
975             command[0] = SHORT_HEADER2[0];
976             command[1] = SHORT_HEADER2[1];
977             NWCopyMtx22Reverse(reinterpret_cast<f32*>(&command[2]), data);
978             // アドレスヘッダで2Word進める
979             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x2 );
980             break;
981         }
982         case MATRIX3x2:
983         {
984             command[0] = LONG_HEADER[0];
985             command[1] = LONG_HEADER[1];
986             NWCopyMtx32WithHeader(
987                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x2 * REG_COUNT - 1) << SIZE_SHIFT));
988             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
989             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x2) * sizeof(f32) );
990             break;
991         }
992         case MATRIX4x2:
993         {
994             command[0] = LONG_HEADER[0];
995             command[1] = LONG_HEADER[1];
996             NWCopyMtx42WithHeader(
997                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x2 * REG_COUNT - 1) << SIZE_SHIFT));
998             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
999             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x2) * sizeof(f32) );
1000             break;
1001         }
1002         default:
1003         {
1004             NW_FATAL_ERROR("Not supported yet.\n");
1005             break;
1006         }
1007     }
1008 }
1009 
1010 //---------------------------------------------------------------------------
1011 //! @brief        ユニフォーム値をGPUへ送信します。
1012 //!
1013 //! @param[in]    index   シェーダユニフォームのインデクスです。
1014 //! @param[in]    count   設定するユニフォーム数です。
1015 //! @param[in]    data    設定データ列の先頭アドレスです。
1016 //---------------------------------------------------------------------------
1017 template <u32 RegFloatIndex>
1018 NW_FORCE_INLINE void
NWSetUniform1fv(u32 index,int count,const f32 * data)1019 NWSetUniform1fv(u32 index, int count, const f32* data)
1020 {
1021 #if defined(NW_UNIFORM_DUMP)
1022     NW_LOG("Set Uniform 1fv: %d\n", index);
1023 #endif
1024 
1025     enum
1026     {
1027         REG_UNIFORM_FLOAT_INDEX = RegFloatIndex,
1028         REG_UNIFORM_FLOAT_BASE  = REG_UNIFORM_FLOAT_INDEX + 1,
1029         SIZE_SHIFT = 20,
1030         VECTOR1 = 1,
1031         MATRIX2x1 = 2,
1032         MATRIX3x1 = 3,
1033         MATRIX4x1 = 4,
1034         // データの存在しない領域には 0.0f を設定するのでレジスタは常に4。
1035         REG_COUNT = 4
1036     };
1037 
1038      // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。
1039     NW_MINMAX_ASSERT(count, 1, 64);
1040     NW_NULL_ASSERT( data );
1041     NW_MINMAX_ASSERT(index, 0, 96);
1042 
1043     const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF);
1044 
1045     // レジスタが2本以下の場合は、1コマンドで送信可能。
1046     const u32 SHORT_HEADER[2] =
1047     {
1048         0x80000000 + index,
1049         SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT)
1050     };
1051 
1052     // レジスタが2本以下の場合は、1コマンドで送信可能。
1053     const u32 SHORT_HEADER2[2] =
1054     {
1055         0x80000000 + index,
1056         SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT)
1057     };
1058 
1059     // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。
1060     const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF);
1061     const u32 LONG_VALUE_HEADER   = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF);
1062 
1063     const u32 LONG_HEADER[2] =
1064     {
1065         0x80000000 + index,
1066         LONG_ADDRESS_HEADER
1067     };
1068 
1069     u32* command = (u32*)NWGetCurrentCmdBuffer();
1070 
1071     switch (count)
1072     {
1073         case VECTOR1:
1074         {
1075             command[0] = SHORT_HEADER[0];
1076             command[1] = SHORT_HEADER[1];
1077             NWCopyVec1Reverse(reinterpret_cast<f32*>(&command[2]), data);
1078             // アドレスヘッダで2Word進める
1079             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT );
1080             break;
1081         }
1082         case MATRIX2x1:
1083         {
1084             command[0] = SHORT_HEADER2[0];
1085             command[1] = SHORT_HEADER2[1];
1086             NWCopyMtx21Reverse(reinterpret_cast<f32*>(&command[2]), data);
1087             // アドレスヘッダで2Word進める
1088             NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x1 );
1089             break;
1090         }
1091         case MATRIX3x1:
1092         {
1093             command[0] = LONG_HEADER[0];
1094             command[1] = LONG_HEADER[1];
1095             NWCopyMtx31WithHeader(
1096                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x1 * REG_COUNT - 1) << SIZE_SHIFT));
1097             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
1098             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x1) * sizeof(f32) );
1099             break;
1100         }
1101         case MATRIX4x1:
1102         {
1103             command[0] = LONG_HEADER[0];
1104             command[1] = LONG_HEADER[1];
1105             NWCopyMtx41WithHeader(
1106                 reinterpret_cast<f32*>(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x1 * REG_COUNT - 1) << SIZE_SHIFT));
1107             // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める
1108             NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x1) * sizeof(f32) );
1109             break;
1110         }
1111         default:
1112         {
1113             NW_FATAL_ERROR("Not supported yet.\n");
1114             break;
1115         }
1116     }
1117 }
1118 
1119 //---------------------------------------------------------------------------
1120 //! @brief        ユニフォーム値をGPUへ送信します。
1121 //!
1122 //! @param[in]    index   シェーダユニフォームのインデクスです。
1123 //! @param[in]    totalCount 一度に送信するレジスタ数です。
1124 //! @param[in]    data    設定データ列の先頭アドレスです。
1125 //! @param[in]    count   設定するユニフォーム数です。
1126 //---------------------------------------------------------------------------
1127 template <u32 RegFloatIndex>
1128 NW_FORCE_INLINE void
NWSetUniform4fvBegin(u32 index,int totalCount,int count,const f32 * data)1129 NWSetUniform4fvBegin(u32 index, int totalCount, int count, const f32* data)
1130 {
1131 #if defined(NW_UNIFORM_DUMP)
1132     NW_LOG("Set Uniform 4fv Begin: %d\n", index);
1133 #endif
1134 
1135     enum
1136     {
1137         REG_UNIFORM_FLOAT_INDEX = RegFloatIndex,
1138         REG_UNIFORM_FLOAT_BASE = REG_UNIFORM_FLOAT_INDEX + 1,
1139         SIZE_SHIFT = 20,
1140         VECTOR4 = 1,
1141         MATRIX2x4 = 2,
1142         MATRIX3x4 = 3,
1143         MATRIX4x4 = 4,
1144         REG_COUNT = 4
1145     };
1146 
1147     const u32 ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF);
1148     const u32 VALUE_HEADER   = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF);
1149 
1150      // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。
1151     NW_MINMAX_ASSERT(count, 1, 64);
1152     NW_MINMAX_ASSERT(totalCount, 1, 64);
1153     NW_NULL_ASSERT( data );
1154     NW_MINMAX_ASSERT(index, 0, 96);
1155 
1156     // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。
1157     const u32 HEADER[2] =
1158     {
1159         0x80000000 + index,
1160         ADDRESS_HEADER
1161     };
1162 
1163     u32* command = (u32*)NWGetCurrentCmdBuffer();
1164     command[0] = HEADER[0];
1165     command[1] = HEADER[1];
1166 
1167     switch (count)
1168     {
1169         case VECTOR4:
1170         {
1171             NWCopyVec4WithHeader(
1172                 reinterpret_cast<f32*>(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT));
1173             // アドレスヘッダで2Word、バリューヘッダで1Word進める
1174             NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * VECTOR4) * sizeof(f32) );
1175             break;
1176         }
1177         case MATRIX2x4:
1178         {
1179             NWCopyMtx24WithHeader(
1180                 reinterpret_cast<f32*>(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT));
1181             // アドレスヘッダで2Word、バリューヘッダで1Word進める
1182             NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * MATRIX2x4) * sizeof(f32) );
1183             break;
1184         }
1185         case MATRIX3x4:
1186         {
1187             NWCopyMtx34WithHeader(
1188                 reinterpret_cast<f32*>(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT));
1189             // アドレスヘッダで2Word、バリューヘッダで1Word進める
1190             NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * MATRIX3x4) * sizeof(f32) );
1191             break;
1192         }
1193         case MATRIX4x4:
1194         {
1195             NWCopyMtx44WithHeader(
1196                 reinterpret_cast<f32*>(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT));
1197             // アドレスヘッダで2Word、バリューヘッダで1Word進める
1198             NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * MATRIX4x4) * sizeof(f32) );
1199             break;
1200         }
1201         default:
1202         {
1203             NW_FATAL_ERROR("Not supported yet.\n");
1204             break;
1205         }
1206     }
1207 }
1208 
1209 //---------------------------------------------------------------------------
1210 //! @brief        ユニフォーム値をGPUへ送信します。
1211 //!
1212 //! @param[in]    data    設定データ列の先頭アドレスです。
1213 //! @param[in]    count   設定するユニフォーム数です。
1214 //---------------------------------------------------------------------------
1215 NW_FORCE_INLINE void
NWSetUniform4fvContinuous(int count,const f32 * data)1216 NWSetUniform4fvContinuous(int count, const f32* data)
1217 {
1218 #if defined(NW_UNIFORM_DUMP)
1219     NW_LOG("Set Uniform 4fv Continuous: %d\n");
1220 #endif
1221 
1222     enum
1223     {
1224         VECTOR4 = 1,
1225         MATRIX2x4 = 2,
1226         MATRIX3x4 = 3,
1227         MATRIX4x4 = 4,
1228         REG_COUNT = 4
1229     };
1230 
1231     f32* command = (f32*)NWGetCurrentCmdBuffer();
1232 
1233     switch (count)
1234     {
1235         case VECTOR4:
1236         {
1237             NWCopyVec4Reverse(command, data);
1238             NWForwardCurrentCmdBuffer( (REG_COUNT * VECTOR4) * sizeof(f32) );
1239             break;
1240         }
1241         case MATRIX2x4:
1242         {
1243             NWCopyMtx24Reverse(command, data);
1244             NWForwardCurrentCmdBuffer( (REG_COUNT * MATRIX2x4) * sizeof(f32) );
1245             break;
1246         }
1247         case MATRIX3x4:
1248         {
1249             NWCopyMtx34Reverse(command, data);
1250             NWForwardCurrentCmdBuffer( (REG_COUNT * MATRIX3x4) * sizeof(f32) );
1251             break;
1252         }
1253         case MATRIX4x4:
1254         {
1255             NWCopyMtx44Reverse(command, data);
1256             NWForwardCurrentCmdBuffer( (REG_COUNT * MATRIX4x4) * sizeof(f32) );
1257             break;
1258         }
1259         default:
1260         {
1261             NW_FATAL_ERROR("Not supported yet.\n");
1262             break;
1263         }
1264     }
1265 }
1266 
1267 //---------------------------------------------------------------------------
1268 //! @brief        ユニフォーム値をGPUへ送信します。
1269 //---------------------------------------------------------------------------
1270 NW_FORCE_INLINE void
NWSetUniform4fvEnd()1271 NWSetUniform4fvEnd()
1272 {
1273 #if defined(NW_UNIFORM_DUMP)
1274     NW_LOG("Set Uniform 4fv End: %d\n");
1275 #endif
1276 
1277     NWForwardCurrentCmdBuffer( sizeof(f32) );
1278 }
1279 
1280 NW_FORCE_INLINE void
NWSetVertexUniform4fv(u32 index,int count,const f32 * data)1281 NWSetVertexUniform4fv(u32 index, int count, const f32* data)
1282 {
1283     NWSetUniform4fv<REG_VERTEX_UNIFORM_FLOAT_INDEX>(index, count, data);
1284 }
1285 
1286 NW_FORCE_INLINE void
NWSetVertexUniform3fv(u32 index,int count,const f32 * data)1287 NWSetVertexUniform3fv(u32 index, int count, const f32* data)
1288 {
1289     NWSetUniform3fv<REG_VERTEX_UNIFORM_FLOAT_INDEX>(index, count, data);
1290 }
1291 
1292 NW_FORCE_INLINE void
NWSetVertexUniform2fv(u32 index,int count,const f32 * data)1293 NWSetVertexUniform2fv(u32 index, int count, const f32* data)
1294 {
1295     NWSetUniform2fv<REG_VERTEX_UNIFORM_FLOAT_INDEX>(index, count, data);
1296 }
1297 
1298 NW_FORCE_INLINE void
NWSetVertexUniform1fv(u32 index,int count,const f32 * data)1299 NWSetVertexUniform1fv(u32 index, int count, const f32* data)
1300 {
1301     NWSetUniform1fv<REG_VERTEX_UNIFORM_FLOAT_INDEX>(index, count, data);
1302 }
1303 
1304 NW_FORCE_INLINE void
NWSetGeometryUniform4fv(u32 index,int count,const f32 * data)1305 NWSetGeometryUniform4fv(u32 index, int count, const f32* data)
1306 {
1307     NWSetUniform4fv<REG_GEOMETRY_UNIFORM_FLOAT_INDEX>(index, count, data);
1308 }
1309 
1310 NW_FORCE_INLINE void
NWSetGeometryUniform3fv(u32 index,int count,const f32 * data)1311 NWSetGeometryUniform3fv(u32 index, int count, const f32* data)
1312 {
1313     NWSetUniform3fv<REG_GEOMETRY_UNIFORM_FLOAT_INDEX>(index, count, data);
1314 }
1315 
1316 NW_FORCE_INLINE void
NWSetGeometryUniform2fv(u32 index,int count,const f32 * data)1317 NWSetGeometryUniform2fv(u32 index, int count, const f32* data)
1318 {
1319     NWSetUniform2fv<REG_GEOMETRY_UNIFORM_FLOAT_INDEX>(index, count, data);
1320 }
1321 
1322 NW_FORCE_INLINE void
NWSetGeometryUniform1fv(u32 index,int count,const f32 * data)1323 NWSetGeometryUniform1fv(u32 index, int count, const f32* data)
1324 {
1325     NWSetUniform1fv<REG_GEOMETRY_UNIFORM_FLOAT_INDEX>(index, count, data);
1326 }
1327 
1328 NW_FORCE_INLINE void
NWSetVertexUniform4fvBegin(u32 index,int totalCount,int count,const f32 * data)1329 NWSetVertexUniform4fvBegin(u32 index, int totalCount, int count, const f32* data)
1330 {
1331     NWSetUniform4fvBegin<REG_VERTEX_UNIFORM_FLOAT_INDEX>(index, totalCount, count, data);
1332 }
1333 
1334 NW_FORCE_INLINE void
NWSetVertexUniform4fvContinuous(int count,const f32 * data)1335 NWSetVertexUniform4fvContinuous(int count, const f32* data)
1336 {
1337     NWSetUniform4fvContinuous(count, data);
1338 }
1339 
1340 NW_FORCE_INLINE void
NWSetVertexUniform4fvEnd()1341 NWSetVertexUniform4fvEnd()
1342 {
1343     NWSetUniform4fvEnd();
1344 }
1345 
1346 NW_FORCE_INLINE void
NWSetGeometryUniform4fvBegin(u32 index,int totalCount,int count,const f32 * data)1347 NWSetGeometryUniform4fvBegin(u32 index, int totalCount, int count, const f32* data)
1348 {
1349     NWSetUniform4fvBegin<REG_GEOMETRY_UNIFORM_FLOAT_INDEX>(index, totalCount, count, data);
1350 }
1351 
1352 NW_FORCE_INLINE void
NWSetGeometryUniform4fvContinuous(int count,const f32 * data)1353 NWSetGeometryUniform4fvContinuous(int count, const f32* data)
1354 {
1355     NWSetUniform4fvContinuous(count, data);
1356 }
1357 
1358 NW_FORCE_INLINE void
NWSetGeometryUniform4fvEnd()1359 NWSetGeometryUniform4fvEnd()
1360 {
1361     NWSetUniform4fvEnd();
1362 }
1363 
1364 
1365 //---------------------------------------------------------------------------
1366 //! @brief        コマンドバッファを構築する際のアドレス管理をするクラスです。
1367 //---------------------------------------------------------------------------
1368 class CommandBufferInfo
1369 {
1370 public:
1371 
1372     enum BufferResult
1373     {
1374         RESULT_OK            = 0,     //!< 成功を示すリザルト値です。
1375         RESULT_OUT_OF_MEMORY = 1 << 1 //!< メモリ溢れによる失敗を示すリザルト値です。
1376     };
1377 
1378     //---------------------------------------------------------------------------
1379     //! @brief        コンストラクタです。
1380     //!
1381     //! @param[out]   buffer  コマンドを構築するバッファの先頭アドレスです。
1382     //! @param[in]    size    バッファサイズです。
1383     //---------------------------------------------------------------------------
CommandBufferInfo(void * buffer,size_t size)1384     CommandBufferInfo(void* buffer, size_t size)
1385     {
1386         m_TopAddress     = static_cast<u8*>( buffer );
1387         m_CurrentAddress = m_TopAddress;
1388         m_Size           = size;
1389         m_BottomAddress  = reinterpret_cast<u8*>(nw::ut::AddOffsetToPtr( m_TopAddress, size ));
1390     }
1391 
1392     //---------------------------------------------------------------------------
1393     //! @brief        デフォルトコンストラクタです。 gl のカレントコマンドバッファを使用します。
1394     //---------------------------------------------------------------------------
CommandBufferInfo()1395     CommandBufferInfo()
1396     {
1397         m_TopAddress     = NULL;
1398         m_CurrentAddress = NULL;
1399         m_Size           = 0;
1400         m_BottomAddress  = NULL;
1401     }
1402 
1403     //---------------------------------------------------------------------------
1404     //! @brief        現在の書き込み位置のポインタを取得します。
1405     //!
1406     //! @return       現在の書き込み位置のポインタです。
1407     //---------------------------------------------------------------------------
GetCurrentAddress()1408     u8*  GetCurrentAddress()
1409     {
1410         return (m_CurrentAddress != NULL)? m_CurrentAddress : reinterpret_cast<u8*>(__cb_current_command_buffer);
1411     }
1412 
1413     //---------------------------------------------------------------------------
1414     //! @brief        現在の書き込み位置の const ポインタを取得します。
1415     //!
1416     //! @return       現在の書き込み位置のポインタです。
1417     //---------------------------------------------------------------------------
GetCurrentAddress()1418     const u8* GetCurrentAddress() const
1419     {
1420         return (m_CurrentAddress != NULL)? m_CurrentAddress : reinterpret_cast<const u8*>(__cb_current_command_buffer);
1421     }
1422 
1423     //---------------------------------------------------------------------------
1424     //! @brief        バッファの先頭からカレントまでのサイズを取得します。
1425     //!
1426     //! @return       書き込み済みのデータサイズです。
1427     //---------------------------------------------------------------------------
GetCurrentSize()1428     size_t GetCurrentSize() const { return nw::ut::GetOffsetFromPtr( m_TopAddress, m_CurrentAddress ); }
1429 
1430     //---------------------------------------------------------------------------
1431     //! @brief        カレントの書き込み位置のバッファを先に進めます。
1432     //!
1433     //! @param[in]    size    ポインタを進めるサイズです。
1434     //!
1435     //! @return       結果を返します。
1436     //---------------------------------------------------------------------------
1437     Result
ForwardCommand(int size)1438     ForwardCommand(int size)
1439     {
1440         if (!this->CheckRestMemory(size))
1441         {
1442             return Result(RESULT_OUT_OF_MEMORY);
1443         }
1444 
1445         this->ForwardAddress(size);
1446 
1447         return Result(RESULT_OK);
1448     }
1449 
1450     //---------------------------------------------------------------------------
1451     //! @brief        コマンドをカレント位置にコピーします。
1452     //!
1453     //! @param[out]   buffer  コマンドのはいったバッファのアドレスです。
1454     //! @param[in]    size    バッファサイズです。
1455     //!
1456     //! @return       結果です。
1457     //---------------------------------------------------------------------------
1458     Result
PutCommand(const void * buffer,int size)1459     PutCommand(const void* buffer, int size)
1460     {
1461         NW_NULL_ASSERT(buffer);
1462         NW_ASSERT(size > 0);
1463         NW_ALIGN_ASSERT(size, 4);
1464 
1465         if (!this->CheckRestMemory(size))
1466         {
1467             return Result(RESULT_OUT_OF_MEMORY);
1468         }
1469 
1470         nw::os::MemCpy(this->GetCurrentAddress(), buffer, size);
1471 
1472         this->ForwardAddress(size);
1473 
1474         return Result(RESULT_OK);
1475     }
1476 
1477     //---------------------------------------------------------------------------
1478     //! @brief        コマンドをカレント位置にコピーします。
1479     //!
1480     //! @param[out]   buffer  コマンドのはいったバッファのアドレスです。
1481     //! @param[in]    size    バッファサイズです。
1482     //!
1483     //! @return       結果です。
1484     //---------------------------------------------------------------------------
1485     template <int size>
1486     Result
PutCommand(const void * buffer)1487     PutCommand(const void* buffer)
1488     {
1489         NW_NULL_ASSERT(buffer);
1490         NW_STATIC_ASSERT(size > 0);
1491         NW_STATIC_ASSERT((size % 4) == 0);
1492 
1493         if (!this->CheckRestMemory(size))
1494         {
1495             return Result(RESULT_OUT_OF_MEMORY);
1496         }
1497 
1498         internal::FastWordCopy((u32*)this->GetCurrentAddress(), (u32*)buffer, size);
1499 
1500         this->ForwardAddress(size);
1501     }
1502 
1503 private:
1504     u8*    m_TopAddress;     //!< 先頭アドレスです。
1505     u8*    m_BottomAddress;  //!< 終端アドレスです。
1506     u8*    m_CurrentAddress; //!< 現在の書き込み位置のアドレスです。
1507     size_t m_Size;           //!< バッファサイズです。
1508 
1509     //---------------------------------------------------------------------------
1510     //! @brief        残りメモリが足りるかどうかをチェックします。
1511     //!
1512     //! @param[in]    size    残りメモリと比較する使用予定のデータサイズです。
1513     //!
1514     //! @return       メモリが足りている場合は true, 足りない場合は false を返します。
1515     //---------------------------------------------------------------------------
CheckRestMemory(size_t size)1516     bool CheckRestMemory(size_t size)
1517     {
1518         if (m_CurrentAddress == NULL)
1519         {
1520             return nw::ut::AddOffsetToPtr(__cb_current_command_buffer, size) <= __cb_current_max_command_buffer;
1521         }
1522         else
1523         {
1524             return nw::ut::AddOffsetToPtr(m_CurrentAddress, size) <= m_BottomAddress;
1525         }
1526     }
1527 
1528     //---------------------------------------------------------------------------
1529     //! @brief        エラーチェックなしで、カレントのポインタを進めます。
1530     //!
1531     //! @param[in]    size    ポインタを進めるサイズです。
1532     //---------------------------------------------------------------------------
ForwardAddress(int size)1533     void ForwardAddress(int size)
1534     {
1535         if (m_CurrentAddress != NULL)
1536         {
1537             m_CurrentAddress += size;
1538         }
1539         else
1540         {
1541             NWForwardCurrentCmdBuffer(size);
1542         }
1543     }
1544 };
1545 
1546 
1547 //---------------------------------------------------------------------------
1548 //! @brief        PubCommand の特殊化版です。サイズ毎に最適化したコピーを実装しています。
1549 //!
1550 //! @param[in]    buffer コピー元のバッファです。
1551 //!
1552 //! @return       結果を返します。バッファサイズが足りなくなった場合に RESULT_OUT_OF_MEMORY を返します。
1553 //---------------------------------------------------------------------------
1554 template <>
1555 NW_INLINE Result
1556 CommandBufferInfo::PutCommand<4>(const void* buffer)
1557 {
1558     NW_NULL_ASSERT( buffer );
1559 
1560     if (!this->CheckRestMemory(4))
1561     {
1562         return Result(CommandBufferInfo::RESULT_OUT_OF_MEMORY);
1563     }
1564 
1565     *reinterpret_cast<u32*>(this->GetCurrentAddress()) = *reinterpret_cast<const u32*>(buffer);
1566     this->ForwardAddress(4);
1567 
1568     return Result(CommandBufferInfo::RESULT_OK);
1569 }
1570 
1571 template <>
1572 NW_INLINE Result
1573 CommandBufferInfo::PutCommand<8>(const void* buffer)
1574 {
1575     NW_NULL_ASSERT( buffer );
1576 
1577     if (!this->CheckRestMemory(8))
1578     {
1579         return Result(CommandBufferInfo::RESULT_OUT_OF_MEMORY);
1580     }
1581 
1582     *reinterpret_cast<u64*>(this->GetCurrentAddress()) = *reinterpret_cast<const u64*>(buffer);
1583     this->ForwardAddress(8);
1584 
1585     return Result(CommandBufferInfo::RESULT_OK);
1586 }
1587 
1588 template <>
1589 NW_INLINE Result
1590 CommandBufferInfo::PutCommand<12>(const void* buffer)
1591 {
1592     NW_NULL_ASSERT( buffer );
1593 
1594     if (!this->CheckRestMemory(12))
1595     {
1596         return Result(CommandBufferInfo::RESULT_OUT_OF_MEMORY);
1597     }
1598 
1599     *reinterpret_cast<u64*>(this->GetCurrentAddress()) = *reinterpret_cast<const u64*>(buffer);
1600     *reinterpret_cast<u32*>(this->GetCurrentAddress() + 8) = *(reinterpret_cast<const u32*>(buffer) + 2);
1601     this->ForwardAddress(12);
1602 
1603     return Result(CommandBufferInfo::RESULT_OK);
1604 }
1605 
1606 template <>
1607 NW_INLINE Result
1608 CommandBufferInfo::PutCommand<16>(const void* buffer)
1609 {
1610     NW_NULL_ASSERT( buffer );
1611 
1612     if (!this->CheckRestMemory(16))
1613     {
1614         return (CommandBufferInfo::RESULT_OUT_OF_MEMORY);
1615     }
1616 
1617     *reinterpret_cast<u64*>(this->GetCurrentAddress()) = *reinterpret_cast<const u64*>(buffer);
1618     *reinterpret_cast<u64*>(this->GetCurrentAddress() + 8) = *(reinterpret_cast<const u64*>(buffer) + 1);
1619     this->ForwardAddress(16);
1620 
1621     return Result(CommandBufferInfo::RESULT_OK);
1622 }
1623 
1624 
1625 
1626 //---------------------------------------------------------------------------
1627 //! @brief        コマンドの保存、デバッグ用クラスです。
1628 //---------------------------------------------------------------------------
1629 class CommandCacheBuilder
1630 {
1631 public:
1632     //---------------------------------------------------------------------------
1633     //! @brief        コンストラクタです。
1634     //---------------------------------------------------------------------------
CommandCacheBuilder()1635     CommandCacheBuilder() : m_StartAddr(NULL), m_EndAddr(NULL) {}
1636 
1637     //---------------------------------------------------------------------------
1638     //! @brief        コマンド保存の開始位置を記録します。
1639     //---------------------------------------------------------------------------
Begin()1640     void Begin()
1641     {
1642         m_StartAddr = NWGetCurrentCmdBuffer();
1643     }
1644 
1645     //---------------------------------------------------------------------------
1646     //! @brief        コマンド保存の終端位置を記録します。
1647     //---------------------------------------------------------------------------
End()1648     void End()
1649     {
1650         if (m_StartAddr)
1651         {
1652             m_EndAddr = NWGetCurrentCmdBuffer();
1653         }
1654     }
1655 
1656     //---------------------------------------------------------------------------
1657     //! @brief        コマンドバッファのカレントポインタをBeginの時点に巻き戻します。
1658     //---------------------------------------------------------------------------
Rollback()1659     void Rollback()
1660     {
1661         void* current = NWGetCurrentCmdBuffer();
1662 
1663         NWBackwardCurrentCmdBuffer( ut::GetOffsetFromPtr(m_StartAddr, current) );
1664     }
1665 
1666     //---------------------------------------------------------------------------
1667     //! @brief        コマンド保存の状態をリセットします。
1668     //---------------------------------------------------------------------------
Reset()1669     void Reset()
1670     {
1671         m_StartAddr = NULL;
1672         m_EndAddr = NULL;
1673     }
1674 
1675     //---------------------------------------------------------------------------
1676     //! @brief        カレントの保存するべきコマンドのサイズを取得します。
1677     //!
1678     //! @return       AllocAndCopy 関数で保存されるコマンドサイズです。
1679     //---------------------------------------------------------------------------
GetSize()1680     s32 GetSize()
1681     {
1682         if (m_StartAddr && m_EndAddr)
1683         {
1684             return ut::GetOffsetFromPtr(m_StartAddr, m_EndAddr);
1685         }
1686         return 0;
1687     }
1688 
1689     //---------------------------------------------------------------------------
1690     //! @brief        Begin 関数、End 関数で保存位置を記録した後に、
1691     //!               実際に確保したバッファへのコピーをおこないます。
1692     //---------------------------------------------------------------------------
1693     void* AllocAndCopy(nw::os::IAllocator* allocator = NULL)
1694     {
1695         s32 size = this->GetSize();
1696 
1697         if (size == 0) { return NULL; }
1698 
1699         void* buffer;
1700 
1701         if (allocator != NULL) { buffer = allocator->Alloc(size, 4); }
1702         else { buffer = CommandCacheManager::Allocate(size); }
1703 
1704         if (! buffer ) { return NULL; }
1705 
1706         nw::os::MemCpy(buffer, m_StartAddr, size);
1707 
1708         return buffer;
1709     }
1710 
1711     //---------------------------------------------------------------------------
1712     //! @brief        Begin 関数、End 関数で記録された間のコマンドを標準出力に表示します。
1713     //---------------------------------------------------------------------------
1714     void Report(bool detail = false)
1715     {
1716         if (this->GetSize() == 0) { return; }
1717 
1718         {
1719             u32* addr = reinterpret_cast<u32*>(m_StartAddr);
1720             u32* endAddr = reinterpret_cast<u32*>(m_EndAddr);
1721 
1722             NW_LOG("----------\n");
1723 
1724             char tmpStr[256];
1725             s32 offset = 0;
1726             int count = 0;
1727             while (addr < endAddr)
1728             {
1729                 offset += nw::ut::snprintf(&tmpStr[offset], 256 - offset, 256 - offset, "0x%08x, ", *addr);
1730                 ++addr;
1731                 ++count;
1732                 if (count == 4)
1733                 {
1734                     NN_LOG("%s\n", tmpStr);
1735                     offset = 0;
1736                     count = 0;
1737                 }
1738             }
1739 
1740             if (offset > 0)
1741             {
1742                 NW_LOG("%s\n", tmpStr);
1743             }
1744         }
1745 
1746         if (detail)
1747         {
1748             struct command_t
1749             {
1750                 // data
1751                 u32 data : 32;
1752 
1753                 // header
1754                 u32 addr : 16;
1755                 u32 be   : 4;
1756                 u32 size : 7;
1757                 u32 rsv  : 4;
1758                 u32 seq  : 1;
1759             };
1760 
1761             u32* addr = reinterpret_cast<u32*>(m_StartAddr);
1762             u32* endAddr = reinterpret_cast<u32*>(m_EndAddr);
1763 
1764             NW_LOG("---- Detail ------\n");
1765             NN_LOG("Size : %d\n", this->GetSize());
1766 
1767             while (addr < endAddr)
1768             {
1769                 command_t* command = (command_t*)addr;
1770                 u32* command_u32 = (u32*)addr;
1771 
1772                 int commandSize = (command->size + 1) & ~1;
1773                 commandSize += 2;
1774 
1775                 addr += commandSize;
1776 
1777                 NN_LOG("Raw Data:");
1778                 for (int i = 0; i < commandSize; i += 2)
1779                 {
1780                     if (&command_u32[i] >= endAddr) // 安全のため
1781                     {
1782                         commandSize = i - 2;
1783                         break;
1784                     }
1785 
1786                     if (i != 0 && i % 8 == 0)
1787                     {
1788                         NN_LOG("\n         ");
1789                     }
1790 
1791                     NN_LOG(" 0x%08x, 0x%08x,",
1792                         command_u32[i],
1793                         command_u32[i + 1]);
1794                 }
1795 
1796                 NN_LOG("\n");
1797 
1798                 NN_LOG("addr : 0x%x\n", command->addr);
1799                 NN_LOG("be   : 0x%x\n", command->be);   // バイトイネーブル
1800                 NN_LOG("size : 0x%x (%d)\n", command->size, command->seq); // データの個数-1 0:シングル >1:バースト
1801                 NN_LOG("rsv  : 0x%x\n", command->rsv);
1802                 NN_LOG("seq  : 0x%x\n", command->seq);
1803 
1804                 NN_LOG("data : 0x%x (%f),\n",
1805                     command->data,
1806                     nn::math::U32AsF32(command->data));
1807 
1808                 for (int i = 2; i < commandSize; i += 2)
1809                 {
1810                     if ((i - 2) % 4 == 0)
1811                     {
1812                         NN_LOG("\n      ");
1813                     }
1814 
1815                     NN_LOG(" 0x%x (%f), 0x%x (%f),",
1816                         command_u32[i],
1817                         nn::math::U32AsF32(command_u32[i]),
1818                         command_u32[i + 1],
1819                         nn::math::U32AsF32(command_u32[i + 1]));
1820                 }
1821 
1822                 if (commandSize != 2)
1823                 {
1824                     NN_LOG("\n\n");
1825                 }
1826                 else
1827                 {
1828                     NN_LOG("\n");
1829                 }
1830             }
1831         }
1832     }
1833 
1834 private:
1835     void* m_StartAddr;
1836     void* m_EndAddr;
1837 };
1838 
1839 
1840 } // namespace internal
1841 } // namespace gfx
1842 } // namespace nw
1843 
1844 
1845 #endif // NW_GFX_COMMAND_UTIL_H_
1846