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