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