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