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: 25269 $
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     std::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     std::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 //! @brief        コマンドの保存、デバッグ用クラスです。
1366 //---------------------------------------------------------------------------
1367 class CommandCacheBuilder
1368 {
1369 public:
1370     //---------------------------------------------------------------------------
1371     //! @brief        コンストラクタです。
1372     //---------------------------------------------------------------------------
CommandCacheBuilder()1373     CommandCacheBuilder() : m_StartAddr(NULL), m_EndAddr(NULL) {}
1374 
1375     //---------------------------------------------------------------------------
1376     //! @brief        コマンド保存の開始位置を記録します。
1377     //---------------------------------------------------------------------------
Begin()1378     void Begin()
1379     {
1380         m_StartAddr = NWGetCurrentCmdBuffer();
1381     }
1382 
1383     //---------------------------------------------------------------------------
1384     //! @brief        コマンド保存の終端位置を記録します。
1385     //---------------------------------------------------------------------------
End()1386     void End()
1387     {
1388         if (m_StartAddr)
1389         {
1390             m_EndAddr = NWGetCurrentCmdBuffer();
1391         }
1392     }
1393 
1394     //---------------------------------------------------------------------------
1395     //! @brief        コマンドバッファのカレントポインタをBeginの時点に巻き戻します。
1396     //---------------------------------------------------------------------------
Rollback()1397     void Rollback()
1398     {
1399         void* current = NWGetCurrentCmdBuffer();
1400 
1401         NWBackwardCurrentCmdBuffer( ut::GetOffsetFromPtr(m_StartAddr, current) );
1402     }
1403 
1404     //---------------------------------------------------------------------------
1405     //! @brief        コマンド保存の状態をリセットします。
1406     //---------------------------------------------------------------------------
Reset()1407     void Reset()
1408     {
1409         m_StartAddr = NULL;
1410         m_EndAddr = NULL;
1411     }
1412 
1413     //---------------------------------------------------------------------------
1414     //! @brief        カレントの保存するべきコマンドのサイズを取得します。
1415     //!
1416     //! @return       AllocAndCopy 関数で保存されるコマンドサイズです。
1417     //---------------------------------------------------------------------------
GetSize()1418     s32 GetSize()
1419     {
1420         if (m_StartAddr && m_EndAddr)
1421         {
1422             return ut::GetOffsetFromPtr(m_StartAddr, m_EndAddr);
1423         }
1424         return 0;
1425     }
1426 
1427     //---------------------------------------------------------------------------
1428     //! @brief        Begin 関数、End 関数で保存位置を記録した後に、
1429     //!               実際に確保したバッファへのコピーをおこないます。
1430     //---------------------------------------------------------------------------
1431     void* AllocAndCopy(nw::os::IAllocator* allocator = NULL)
1432     {
1433         s32 size = this->GetSize();
1434 
1435         if (size == 0) { return NULL; }
1436 
1437         void* buffer;
1438 
1439         if (allocator != NULL) { buffer = allocator->Alloc(size, 4); }
1440         else { buffer = CommandCacheManager::Allocate(size); }
1441 
1442         if (! buffer ) { return NULL; }
1443 
1444         std::memcpy(buffer, m_StartAddr, size);
1445 
1446         return buffer;
1447     }
1448 
1449     //---------------------------------------------------------------------------
1450     //! @brief        Begin 関数、End 関数で記録された間のコマンドを標準出力に表示します。
1451     //---------------------------------------------------------------------------
1452     void Report(bool detail = false)
1453     {
1454         if (this->GetSize() == 0) { return; }
1455 
1456         {
1457             u32* addr = reinterpret_cast<u32*>(m_StartAddr);
1458             u32* endAddr = reinterpret_cast<u32*>(m_EndAddr);
1459 
1460             NW_LOG("----------\n");
1461 
1462             char tmpStr[256];
1463             s32 offset = 0;
1464             int count = 0;
1465             while (addr < endAddr)
1466             {
1467                 offset += nw::ut::snprintf(&tmpStr[offset], 256 - offset, 256 - offset, "0x%08x, ", *addr);
1468                 ++addr;
1469                 ++count;
1470                 if (count == 4)
1471                 {
1472                     NN_LOG("%s\n", tmpStr);
1473                     offset = 0;
1474                     count = 0;
1475                 }
1476             }
1477 
1478             if (offset > 0)
1479             {
1480                 NW_LOG("%s\n", tmpStr);
1481             }
1482         }
1483 
1484         if (detail)
1485         {
1486             struct command_t
1487             {
1488                 // data
1489                 u32 data : 32;
1490 
1491                 // header
1492                 u32 addr : 16;
1493                 u32 be   : 4;
1494                 u32 size : 7;
1495                 u32 rsv  : 4;
1496                 u32 seq  : 1;
1497             };
1498 
1499             u32* addr = reinterpret_cast<u32*>(m_StartAddr);
1500             u32* endAddr = reinterpret_cast<u32*>(m_EndAddr);
1501 
1502             NW_LOG("---- Detail ------\n");
1503             NN_LOG("Size : %d\n", this->GetSize());
1504 
1505             while (addr < endAddr)
1506             {
1507                 command_t* command = (command_t*)addr;
1508                 u32* command_u32 = (u32*)addr;
1509 
1510                 int commandSize = (command->size + 1) & ~1;
1511                 commandSize += 2;
1512 
1513                 addr += commandSize;
1514 
1515                 NN_LOG("Raw Data:");
1516                 for (int i = 0; i < commandSize; i += 2)
1517                 {
1518                     if (&command_u32[i] >= endAddr) // 安全のため
1519                     {
1520                         commandSize = i - 2;
1521                         break;
1522                     }
1523 
1524                     if (i != 0 && i % 8 == 0)
1525                     {
1526                         NN_LOG("\n         ");
1527                     }
1528 
1529                     NN_LOG(" 0x%08x, 0x%08x,",
1530                         command_u32[i],
1531                         command_u32[i + 1]);
1532                 }
1533 
1534                 NN_LOG("\n");
1535 
1536                 NN_LOG("addr : 0x%x\n", command->addr);
1537                 NN_LOG("be   : 0x%x\n", command->be);   // バイトイネーブル
1538                 NN_LOG("size : 0x%x (%d)\n", command->size, command->seq); // データの個数-1 0:シングル >1:バースト
1539                 NN_LOG("rsv  : 0x%x\n", command->rsv);
1540                 NN_LOG("seq  : 0x%x\n", command->seq);
1541 
1542                 NN_LOG("data : 0x%x (%f),\n",
1543                     command->data,
1544                     nn::math::U32AsF32(command->data));
1545 
1546                 for (int i = 2; i < commandSize; i += 2)
1547                 {
1548                     if ((i - 2) % 4 == 0)
1549                     {
1550                         NN_LOG("\n      ");
1551                     }
1552 
1553                     NN_LOG(" 0x%x (%f), 0x%x (%f),",
1554                         command_u32[i],
1555                         nn::math::U32AsF32(command_u32[i]),
1556                         command_u32[i + 1],
1557                         nn::math::U32AsF32(command_u32[i + 1]));
1558                 }
1559 
1560                 if (commandSize != 2)
1561                 {
1562                     NN_LOG("\n\n");
1563                 }
1564                 else
1565                 {
1566                     NN_LOG("\n");
1567                 }
1568             }
1569         }
1570     }
1571 
1572 private:
1573     void* m_StartAddr;
1574     void* m_EndAddr;
1575 };
1576 
1577 
1578 } // namespace internal
1579 } // namespace gfx
1580 } // namespace nw
1581 
1582 
1583 #endif // NW_GFX_COMMAND_UTIL_H_
1584