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