/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_CommandUtil.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 25269 $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_COMMAND_UTIL_H_ #define NW_GFX_COMMAND_UTIL_H_ #include #include #include #include #include // #define NW_UNIFORM_DUMP #include #include #include #include namespace nw { namespace gfx { //--------------------------------------------------------------------------- //! @brief コマンドキャッシュ動的生成用のバッファを確保する為のグローバルアロケータ設定です。 //--------------------------------------------------------------------------- class CommandCacheManager { public: //--------------------------------------------------------------------------- //! @brief コマンドキャッシュ確保用のアロケータを設定します。 //! //! @param[out] allocator コマンドキャッシュの確保に使用するアロケータです。 //--------------------------------------------------------------------------- static void SetAllocator(nw::os::IAllocator* allocator) { s_Allocator = allocator; } //--------------------------------------------------------------------------- //! @brief 設定されているアロケータを取得します。 //! //! @return CommandCacheManager に設定されているアロケータです。 //--------------------------------------------------------------------------- static nw::os::IAllocator* GetAllocator() { return s_Allocator; } //--------------------------------------------------------------------------- //! @brief コマンドキャッシュ生成用にアロケートをおこないます。 //! //! @param[in] size 確保するメモリサイズです。 //! //! @return アロケートしたメモリ領域を返します。 //--------------------------------------------------------------------------- static void* Allocate(s32 size) { NW_NULL_ASSERT( s_Allocator ); return s_Allocator->Alloc(size, 4); } //--------------------------------------------------------------------------- //! @brief メモリ領域を開放をおこないます。 //! //! @param[out] buffer 解放をおこなうメモリ領域です。 //--------------------------------------------------------------------------- static void Free(void* buffer) { if (s_Allocator != NULL ) { s_Allocator->Free(buffer); } else { NW_WARNING(false, "No allocator available"); } } private: static nw::os::IAllocator* s_Allocator; }; namespace internal { //--------------------------------------------------------------------------- //! @brief コマンドキャッシュのコマンドヘッダアクセスクラスです。 //--------------------------------------------------------------------------- class CommandHeader { public: //--------------------------------------------------------------------------- //! @brief コンストラクタです。 //! //! @param[in] rawData ヘッダの64bit値です。 //--------------------------------------------------------------------------- CommandHeader(u64 rawData) : m_RawData( rawData >> 32 ) {} //--------------------------------------------------------------------------- //! @brief コンストラクタです。 //! //! @param[in] rawData ヘッダの32bit値です。 //! Little Endian では 2ワード目を与える必要があるのに注意。 //--------------------------------------------------------------------------- CommandHeader(u32 rawData) : m_RawData( rawData ) {} //--------------------------------------------------------------------------- //! @brief レジスタアドレスを取得します。 //! //! @return レジスタアドレスです。 //--------------------------------------------------------------------------- u32 GetAddress() const { return (this->m_RawData & ADDRESS_MASK); } //--------------------------------------------------------------------------- //! @brief 書き込みデータ数を取得します。 //! //! @return 書き込みをおこなうu32データの数です。 //--------------------------------------------------------------------------- s32 GetSize() const { return ((this->m_RawData & SIZE_MASK) >> SIZE_SHIFT) + 1; } //--------------------------------------------------------------------------- //! @brief バイトイネーブルの設定値を取得します。 //! //! @return バイトイネーブルの設定値です。 //--------------------------------------------------------------------------- u8 GetByteEnable() const { return static_cast((this->m_RawData & BYTE_ENABLE_MASK) >> BYTE_ENABLE_SHIFT); } //--------------------------------------------------------------------------- //! @brief バイトイネーブルから生成されるマスクを取得します。 //! //! @return バイトイネーブルから生成されるマスクです。 //--------------------------------------------------------------------------- u32 GetByteEnableMask() const { u8 be = this->GetByteEnable(); u32 mask = 0; mask |= (be & 0x1) ? 0x000000FF : 0; mask |= (be & 0x2) ? 0x0000FF00 : 0; mask |= (be & 0x4) ? 0x00FF0000 : 0; mask |= (be & 0x8) ? 0xFF000000 : 0; return mask; } //--------------------------------------------------------------------------- //! @brief 連続書き込みモードのフラグを取得します。 //! //! @return 連続アドレス書き込みモードは 1 、 //! 単一書き込みモードは 0 を返します。 //--------------------------------------------------------------------------- u32 GetBurstModeFlag() const { return this->m_RawData & BURST_FLAG; } private: enum { ADDRESS_SHIFT = 0, ADDRESS_WIDTH = 16, ADDRESS_MASK = 0xFFFF, BYTE_ENABLE_SHIFT = 16, BYTE_ENABLE_WIDTH = 4, BYTE_ENABLE_MASK = 0xF0000, SIZE_SHIFT = 20, SIZE_WIDTH = 8, SIZE_MASK = 0x0FF00000, BURST_FLAG = 0x80000000 }; //--------------------------------------------------------------------------- //! @brief デフォルトコンストラクタは非公開にしています。 //--------------------------------------------------------------------------- CommandHeader() {} u32 m_RawData; }; //--------------------------------------------------------------------------- //! @brief レジスタの値とシフト、マスク設定から特定のビット位置の値を取得ます。 //! mask 引数には shift がかかっていない 0 ビット目基準のマスク値を設定します。 //! //! @param[in] value レジスタの値です。 //! @param[in] mask shift がかかっていないマスク設定です。 //! @param[in] shift 取り出す値のシフト値です。 //! //! @return shift と mask 設定から取り出された値を取得します。 //--------------------------------------------------------------------------- inline u32 GetCmdValue(u32 value, u32 mask, s32 shift) { return (value >> shift) & mask; } template inline void SetCmdValue(u32* addr, TValue value, u32 mask, s32 shift) { u32 result = *addr & ~(mask << shift); *addr = result | ((static_cast(value) & static_cast(mask)) << shift); } //--------------------------------------------------------------------------- //! @brief Glの管理オブジェクトを設定します。 //--------------------------------------------------------------------------- class GlSystem { public: //! @details :private static void SetGlManagers(void*) {} //! @details :private static void SetGlVbManager(void*) {} //! @details :private static void SetGlTexManager(void*) {} //--------------------------------------------------------------------------- //! @brief 頂点バッファアドレスを取得します。 //! //! @param[in] bufferId vbo のIDです。 //--------------------------------------------------------------------------- static void* GetBufferAddress(u32 bufferId) { s32 addr; glBindBuffer(GL_ARRAY_BUFFER, bufferId); glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_DATA_ADDR_DMP, &addr); NW_GL_ASSERT(); return reinterpret_cast( addr ); } //--------------------------------------------------------------------------- //! @brief 頂点インデックスバッファアドレスを取得します。 //! //! @param[in] bufferId vbo のIDです。 //--------------------------------------------------------------------------- static void* GetElementBufferAddress(u32 bufferId) { s32 addr; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferId); glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_DATA_ADDR_DMP, &addr); NW_GL_ASSERT(); return reinterpret_cast( addr ); } //--------------------------------------------------------------------------- //! @brief テクスチャアドレスを取得します。 //! //! @param[in] texId テクスチャIDです。 //--------------------------------------------------------------------------- static void* GetTextureAddress(u32 texId) { s32 addr; glBindTexture( GL_TEXTURE_2D, texId ); glGetTexParameteriv( GL_TEXTURE_2D, GL_TEXTURE_DATA_ADDR_DMP, &addr ); NW_GL_ASSERT(); return reinterpret_cast(addr); } //--------------------------------------------------------------------------- //! @brief キューブテクスチャのアドレスを取得します。 //! //! @param[in] texId テクスチャIDです。 //! @param[in] face キューブ面のIDです。 //--------------------------------------------------------------------------- static void* GetCubeTextureAddress(u32 texId, int face) { s32 addr[6]; glBindTexture( GL_TEXTURE_CUBE_MAP, texId ); glGetTexParameteriv( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_DATA_ADDR_DMP, &addr[0] ); NW_GL_ASSERT(); return reinterpret_cast(addr[face]); } }; //--------------------------------------------------------------------------- //! @brief 直接バッファを渡せる版が無いので強引に対応。 //! //! @param[out] buffer コマンドのはいったバッファのアドレス。 //! @param[in] size バッファサイズ。 //--------------------------------------------------------------------------- template NW_FORCE_INLINE void NWUseCmdlist(const T* buffer, int size) { #if 0 // SDK の更新で nngxAdd3DCommand の 8byte アライン制限が無くなったらこちらを有効にする。 nngxAdd3DCommand( const_cast(buffer), GLsizei(size), GL_TRUE ); #else NW_ASSERT(size > 0); NW_ALIGN_ASSERT(size, 4); NW_NULL_ASSERT( buffer ); std::memcpy(__cb_current_command_buffer, buffer, size); __cb_current_command_buffer += size >> 2; #endif } template NW_FORCE_INLINE void NWUseCmdlist(const void* buffer) { NW_ASSERT(size > 0); NW_ALIGN_ASSERT(size, 4); NW_NULL_ASSERT( buffer ); #if 1 __cb_current_command_buffer = internal::FastWordCopy((u32*)__cb_current_command_buffer, (u32*)buffer, size); #else std::memcpy(__cb_current_command_buffer, buffer, size); __cb_current_command_buffer += size >> 2; #endif } template <> NW_FORCE_INLINE void NWUseCmdlist<4>(const void* buffer) { NW_NULL_ASSERT( buffer ); *reinterpret_cast(__cb_current_command_buffer) = *reinterpret_cast(buffer); __cb_current_command_buffer += 1; } template <> NW_FORCE_INLINE void NWUseCmdlist<8>(const void* buffer) { NW_NULL_ASSERT( buffer ); *reinterpret_cast(__cb_current_command_buffer) = *reinterpret_cast(buffer); __cb_current_command_buffer += 2; } template <> NW_FORCE_INLINE void NWUseCmdlist<12>(const void* buffer) { NW_NULL_ASSERT( buffer ); *reinterpret_cast(__cb_current_command_buffer) = *reinterpret_cast(buffer); *reinterpret_cast(__cb_current_command_buffer + 2) = *(reinterpret_cast(buffer) + 2); __cb_current_command_buffer += 3; } template <> NW_FORCE_INLINE void NWUseCmdlist<16>(const void* buffer) { NW_NULL_ASSERT( buffer ); *reinterpret_cast(__cb_current_command_buffer) = *reinterpret_cast(buffer); *reinterpret_cast(__cb_current_command_buffer + 2) = *(reinterpret_cast(buffer) + 1); __cb_current_command_buffer += 4; } //--------------------------------------------------------------------------- //! @brief カレントのコマンドリストの、書き込み位置を取得します。 //! //! @return カレントコマンドリストの書き込み位置です。 //--------------------------------------------------------------------------- NW_FORCE_INLINE void* NWGetCurrentCmdBuffer() { return __cb_current_command_buffer; } //--------------------------------------------------------------------------- //! @brief アクティブなコマンドバッファの末尾を取得します。 //! //! @return コマンドバッファの末尾ポインタです。 //--------------------------------------------------------------------------- NW_FORCE_INLINE void* NWGetCmdBufferEnd() { return __cb_current_max_command_buffer; } //--------------------------------------------------------------------------- //! @brief カレントのコマンドリストの、書き込み位置を前に進めます。 //! //! @param[in] size カレントのポイントを進めるバイト数です。 //--------------------------------------------------------------------------- NW_FORCE_INLINE void NWForwardCurrentCmdBuffer(u32 size) { NW_ALIGN_ASSERT(size, 4); __cb_current_command_buffer += size >> 2; } //--------------------------------------------------------------------------- //! @brief カレントのコマンドリストの、書き込み位置を前に進めます。 //! //! @param[in] size カレントのポイントを進めるバイト数です。 //--------------------------------------------------------------------------- NW_FORCE_INLINE void NWBackwardCurrentCmdBuffer(u32 size) { NW_ALIGN_ASSERT(size, 4); __cb_current_command_buffer -= size >> 2; } //--------------------------------------------------------------------------- //! @brief コマンドヘッダを生成します。 //! //! @param[in] address レジスタアドレスです。 //! @param[in] count 書き込みデータ数です。 //! @param[in] incremental 連続アドレスモードかどうかのフラグです。 //! @param[in] byteEnable バイトイネーブルマスクです。 //! //! @return 生成されたコマンドヘッダを返します。 // // |seq:1|rsv:3|size:8|be:4|addr:16| // // seq: 0 の場合単一レジスタ書き込み。 1 の場合は連続レジスタ書き込み。 // rsv: 予約。 // size: 32bitデータの個数 - 1。 // be: 32bit データへのバイト単位のマスク。 // addr: 書き込み先アドレス。 //--------------------------------------------------------------------------- NW_INLINE u32 MakeCommandHeader(u32 address, int count, bool incremental, u8 byteEnable) { enum { ADDRESS_SHIFT = 0, ADDRESS_WIDTH = 16, BYTE_ENABLE_SHIFT = 16, BYTE_ENABLE_WIDTH = 4, SIZE_SHIFT = 20, SIZE_WIDTH = 8, BURST_MODE_SHIFT = 31 }; NW_ASSERT(0 < count && count <= 256); u32 result = 0; if (incremental) { result |= (0x1U << BURST_MODE_SHIFT); } result |= ut::internal::MakeBits(count - 1, SIZE_WIDTH, SIZE_SHIFT); result |= ut::internal::MakeBits(address, ADDRESS_WIDTH, ADDRESS_SHIFT); result |= ut::internal::MakeBits(byteEnable, BYTE_ENABLE_WIDTH, BYTE_ENABLE_SHIFT); return result; } #define NW_GFX_GPU_HEADER(addr, count, incremental, byteEnable) (u32)((incremental << 31) | (count << 20) | (byteEnable << 16) | address) enum UniformRegistry { REG_VERTEX_UNIFORM_FLOAT_INDEX = 0x2C0, REG_VERTEX_UNIFORM_FLOAT_BASE = 0x2C1, REG_GEOMETRY_UNIFORM_FLOAT_INDEX = 0x290, REG_GEOMETRY_UNIFORM_FLOAT_BASE = 0x291 }; //--------------------------------------------------------------------------- //! @brief VEC4をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyVec4Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief VEC4をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyVec4WithHeader(f32* dst, const f32* src, u32 header); //--------------------------------------------------------------------------- //! @brief Matrix2x4をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx24Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix2x4をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx24WithHeader(f32* dst, const f32* src, u32 header); //--------------------------------------------------------------------------- //! @brief Matrix3x4をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx34Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix3x4をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx34WithHeader(f32* dst, const f32* src, u32 header); //--------------------------------------------------------------------------- //! @brief Matrix4x4をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx44Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix4x4をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx44WithHeader(f32* dst, const f32* src, u32 header); //--------------------------------------------------------------------------- //! @brief VEC3をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyVec3Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief VEC3をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyVec3WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix2x3をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx23Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix2x3をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx23WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix3x3をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx33Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix3x3をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx33WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix4x3をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx43Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix4x3をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx43WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief VEC2をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyVec2Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief VEC2をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyVec2WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix2x2をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx22Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix2x2をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx22WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix3x2をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx32Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix3x2をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx32WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix4x2をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx42Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix4x2をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx42WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief VEC1をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyVec1Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief VEC1をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyVec1WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix2x1をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx21Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix2x1をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx21WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix3x1をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx31Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix3x1をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx31WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief Matrix4x1をwzyxの順に逆転してコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx41Reverse(f32* dst, const f32* src); //--------------------------------------------------------------------------- //! @brief Matrix4x1をwzyxの順に逆転してヘッダと共にコピーします。 //--------------------------------------------------------------------------- void NWCopyMtx41WithHeader(f32* dst, const f32* src, u32 header ); //--------------------------------------------------------------------------- //! @brief ユニフォーム値をGPUへ送信します。 //! //! @param[in] index シェーダユニフォームのインデクスです。 //! @param[in] count 設定するユニフォーム数です。 //! @param[in] data 設定データ列の先頭アドレスです。 //--------------------------------------------------------------------------- template NW_FORCE_INLINE void NWSetUniform4fv(u32 index, int count, const f32* data) { #if defined(NW_UNIFORM_DUMP) NW_LOG("Set Uniform 4fv: %d\n", index); #endif enum { REG_UNIFORM_FLOAT_INDEX = RegFloatIndex, REG_UNIFORM_FLOAT_BASE = REG_UNIFORM_FLOAT_INDEX + 1, SIZE_SHIFT = 20, VECTOR4 = 1, MATRIX2x4 = 2, MATRIX3x4 = 3, MATRIX4x4 = 4, REG_COUNT = 4 }; // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。 NW_MINMAX_ASSERT(count, 1, 64); NW_NULL_ASSERT( data ); NW_MINMAX_ASSERT(index, 0, 96); const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF); // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT) }; // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER2[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT) }; // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。 const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF); const u32 LONG_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF); const u32 LONG_HEADER[2] = { 0x80000000 + index, LONG_ADDRESS_HEADER }; u32* command = (u32*)NWGetCurrentCmdBuffer(); switch (count) { case VECTOR4: { command[0] = SHORT_HEADER[0]; command[1] = SHORT_HEADER[1]; NWCopyVec4Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT ); //NWUseCmdlist(data, sizeof(f32) * REG_COUNT); break; } case MATRIX2x4: { command[0] = SHORT_HEADER2[0]; command[1] = SHORT_HEADER2[1]; NWCopyMtx24Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x4 ); //NWUseCmdlist(data, sizeof(f32) * REG_COUNT * MATRIX2x4); break; } case MATRIX3x4: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx34WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x4 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x4) * sizeof(f32) ); //const u32 HEADER[4] = //{ // 0x80000000 + index, // ADDRESS_HEADER, // *reinterpret_cast(&data[0]), // VALUE_HEADER | ((count * 4 - 1) << SIZE_SHIFT) //}; //NWUseCmdlist(HEADER, sizeof(u32) * 4); //NWUseCmdlist(&data[1], sizeof(f32) * (REG_COUNT * MATRIX3x4 - 1)); // 64bit 境界にパディング //NWUseCmdlist(&PADDING[0], sizeof(f32)); break; } case MATRIX4x4: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx44WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x4 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x4) * sizeof(f32) ); //const u32 HEADER[4] = //{ // 0x80000000 + index, // ADDRESS_HEADER, // *reinterpret_cast(&data[0]), // VALUE_HEADER | ((count * 4 - 1) << SIZE_SHIFT) //}; //NWUseCmdlist(HEADER, sizeof(u32) * REG_COUNT); //NWUseCmdlist(&data[1], sizeof(f32) * (REG_COUNT * MATRIX4x4 - 1)); // 64bit 境界にパディング //NWUseCmdlist(&PADDING[0], sizeof(f32)); break; } default: { NW_FATAL_ERROR("Not supported yet.\n"); break; } } } //--------------------------------------------------------------------------- //! @brief ユニフォーム値をGPUへ送信します。 //! //! @param[in] index シェーダユニフォームのインデクスです。 //! @param[in] count 設定するユニフォーム数です。 //! @param[in] data 設定データ列の先頭アドレスです。 //--------------------------------------------------------------------------- template NW_FORCE_INLINE void NWSetUniform3fv(u32 index, int count, const f32* data) { #if defined(NW_UNIFORM_DUMP) NW_LOG("Set Uniform 3fv: %d\n", index); #endif enum { REG_UNIFORM_FLOAT_INDEX = RegFloatIndex, REG_UNIFORM_FLOAT_BASE = REG_UNIFORM_FLOAT_INDEX + 1, SIZE_SHIFT = 20, VECTOR3 = 1, MATRIX2x3 = 2, MATRIX3x3 = 3, MATRIX4x3 = 4, // データの存在しない領域には 0.0f を設定するのでレジスタは常に4。 REG_COUNT = 4 }; // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。 NW_MINMAX_ASSERT(count, 1, 64); NW_NULL_ASSERT( data ); NW_MINMAX_ASSERT(index, 0, 96); const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF); // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT) }; // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER2[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT) }; // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。 const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF); const u32 LONG_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF); const u32 LONG_HEADER[2] = { 0x80000000 + index, LONG_ADDRESS_HEADER }; u32* command = (u32*)NWGetCurrentCmdBuffer(); switch (count) { case VECTOR3: { command[0] = SHORT_HEADER[0]; command[1] = SHORT_HEADER[1]; NWCopyVec3Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT ); break; } case MATRIX2x3: { command[0] = SHORT_HEADER2[0]; command[1] = SHORT_HEADER2[1]; NWCopyMtx23Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x3 ); break; } case MATRIX3x3: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx33WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x3 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x3) * sizeof(f32) ); break; } case MATRIX4x3: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx43WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x3 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x3) * sizeof(f32) ); break; } default: { NW_FATAL_ERROR("Not supported yet.\n"); break; } } } //--------------------------------------------------------------------------- //! @brief ユニフォーム値をGPUへ送信します。 //! //! @param[in] index シェーダユニフォームのインデクスです。 //! @param[in] count 設定するユニフォーム数です。 //! @param[in] data 設定データ列の先頭アドレスです。 //--------------------------------------------------------------------------- template NW_FORCE_INLINE void NWSetUniform2fv(u32 index, int count, const f32* data) { #if defined(NW_UNIFORM_DUMP) NW_LOG("Set Uniform 2fv: %d\n", index); #endif enum { REG_UNIFORM_FLOAT_INDEX = RegFloatIndex, REG_UNIFORM_FLOAT_BASE = REG_UNIFORM_FLOAT_INDEX + 1, SIZE_SHIFT = 20, VECTOR2 = 1, MATRIX2x2 = 2, MATRIX3x2 = 3, MATRIX4x2 = 4, // データの存在しない領域には 0.0f を設定するのでレジスタは常に4。 REG_COUNT = 4 }; // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。 NW_MINMAX_ASSERT(count, 1, 64); NW_NULL_ASSERT( data ); NW_MINMAX_ASSERT(index, 0, 96); const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF); // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT) }; // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER2[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT) }; // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。 const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF); const u32 LONG_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF); const u32 LONG_HEADER[2] = { 0x80000000 + index, LONG_ADDRESS_HEADER }; u32* command = (u32*)NWGetCurrentCmdBuffer(); switch (count) { case VECTOR2: { command[0] = SHORT_HEADER[0]; command[1] = SHORT_HEADER[1]; NWCopyVec2Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT ); break; } case MATRIX2x2: { command[0] = SHORT_HEADER2[0]; command[1] = SHORT_HEADER2[1]; NWCopyMtx22Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x2 ); break; } case MATRIX3x2: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx32WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x2 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x2) * sizeof(f32) ); break; } case MATRIX4x2: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx42WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x2 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x2) * sizeof(f32) ); break; } default: { NW_FATAL_ERROR("Not supported yet.\n"); break; } } } //--------------------------------------------------------------------------- //! @brief ユニフォーム値をGPUへ送信します。 //! //! @param[in] index シェーダユニフォームのインデクスです。 //! @param[in] count 設定するユニフォーム数です。 //! @param[in] data 設定データ列の先頭アドレスです。 //--------------------------------------------------------------------------- template NW_FORCE_INLINE void NWSetUniform1fv(u32 index, int count, const f32* data) { #if defined(NW_UNIFORM_DUMP) NW_LOG("Set Uniform 1fv: %d\n", index); #endif enum { REG_UNIFORM_FLOAT_INDEX = RegFloatIndex, REG_UNIFORM_FLOAT_BASE = REG_UNIFORM_FLOAT_INDEX + 1, SIZE_SHIFT = 20, VECTOR1 = 1, MATRIX2x1 = 2, MATRIX3x1 = 3, MATRIX4x1 = 4, // データの存在しない領域には 0.0f を設定するのでレジスタは常に4。 REG_COUNT = 4 }; // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。 NW_MINMAX_ASSERT(count, 1, 64); NW_NULL_ASSERT( data ); NW_MINMAX_ASSERT(index, 0, 96); const u32 SHORT_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, true, 0xF); // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | (REG_COUNT << SIZE_SHIFT) }; // レジスタが2本以下の場合は、1コマンドで送信可能。 const u32 SHORT_HEADER2[2] = { 0x80000000 + index, SHORT_VALUE_HEADER | ((REG_COUNT * 2) << SIZE_SHIFT) }; // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。 const u32 LONG_ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF); const u32 LONG_VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF); const u32 LONG_HEADER[2] = { 0x80000000 + index, LONG_ADDRESS_HEADER }; u32* command = (u32*)NWGetCurrentCmdBuffer(); switch (count) { case VECTOR1: { command[0] = SHORT_HEADER[0]; command[1] = SHORT_HEADER[1]; NWCopyVec1Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT ); break; } case MATRIX2x1: { command[0] = SHORT_HEADER2[0]; command[1] = SHORT_HEADER2[1]; NWCopyMtx21Reverse(reinterpret_cast(&command[2]), data); // アドレスヘッダで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 2 + sizeof(f32) * REG_COUNT * MATRIX2x1 ); break; } case MATRIX3x1: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx31WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX3x1 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + (REG_COUNT * MATRIX3x1) * sizeof(f32) ); break; } case MATRIX4x1: { command[0] = LONG_HEADER[0]; command[1] = LONG_HEADER[1]; NWCopyMtx41WithHeader( reinterpret_cast(&command[2]), data, LONG_VALUE_HEADER | ((MATRIX4x1 * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダとパディングで2Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 4 + ( REG_COUNT * MATRIX4x1) * sizeof(f32) ); break; } default: { NW_FATAL_ERROR("Not supported yet.\n"); break; } } } //--------------------------------------------------------------------------- //! @brief ユニフォーム値をGPUへ送信します。 //! //! @param[in] index シェーダユニフォームのインデクスです。 //! @param[in] totalCount 一度に送信するレジスタ数です。 //! @param[in] data 設定データ列の先頭アドレスです。 //! @param[in] count 設定するユニフォーム数です。 //--------------------------------------------------------------------------- template NW_FORCE_INLINE void NWSetUniform4fvBegin(u32 index, int totalCount, int count, const f32* data) { #if defined(NW_UNIFORM_DUMP) NW_LOG("Set Uniform 4fv Begin: %d\n", index); #endif enum { REG_UNIFORM_FLOAT_INDEX = RegFloatIndex, REG_UNIFORM_FLOAT_BASE = REG_UNIFORM_FLOAT_INDEX + 1, SIZE_SHIFT = 20, VECTOR4 = 1, MATRIX2x4 = 2, MATRIX3x4 = 3, MATRIX4x4 = 4, REG_COUNT = 4 }; const u32 ADDRESS_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_INDEX, 1, false, 0xF); const u32 VALUE_HEADER = MakeCommandHeader(REG_UNIFORM_FLOAT_BASE, 1, false, 0xF); // 1コマンドで送れる最大ワード数は、256ワードなので、レジスタ64本分が限界。 NW_MINMAX_ASSERT(count, 1, 64); NW_MINMAX_ASSERT(totalCount, 1, 64); NW_NULL_ASSERT( data ); NW_MINMAX_ASSERT(index, 0, 96); // レジスタが2本以上の場合は、コマンドを分割し最後に8バイトアラインのパディングが必要。 const u32 HEADER[2] = { 0x80000000 + index, ADDRESS_HEADER }; u32* command = (u32*)NWGetCurrentCmdBuffer(); command[0] = HEADER[0]; command[1] = HEADER[1]; switch (count) { case VECTOR4: { NWCopyVec4WithHeader( reinterpret_cast(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダで1Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * VECTOR4) * sizeof(f32) ); break; } case MATRIX2x4: { NWCopyMtx24WithHeader( reinterpret_cast(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダで1Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * MATRIX2x4) * sizeof(f32) ); break; } case MATRIX3x4: { NWCopyMtx34WithHeader( reinterpret_cast(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダで1Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * MATRIX3x4) * sizeof(f32) ); break; } case MATRIX4x4: { NWCopyMtx44WithHeader( reinterpret_cast(&command[2]), data, VALUE_HEADER | ((totalCount * REG_COUNT - 1) << SIZE_SHIFT)); // アドレスヘッダで2Word、バリューヘッダで1Word進める NWForwardCurrentCmdBuffer( sizeof(u32) * 3 + (REG_COUNT * MATRIX4x4) * sizeof(f32) ); break; } default: { NW_FATAL_ERROR("Not supported yet.\n"); break; } } } //--------------------------------------------------------------------------- //! @brief ユニフォーム値をGPUへ送信します。 //! //! @param[in] data 設定データ列の先頭アドレスです。 //! @param[in] count 設定するユニフォーム数です。 //--------------------------------------------------------------------------- NW_FORCE_INLINE void NWSetUniform4fvContinuous(int count, const f32* data) { #if defined(NW_UNIFORM_DUMP) NW_LOG("Set Uniform 4fv Continuous: %d\n"); #endif enum { VECTOR4 = 1, MATRIX2x4 = 2, MATRIX3x4 = 3, MATRIX4x4 = 4, REG_COUNT = 4 }; f32* command = (f32*)NWGetCurrentCmdBuffer(); switch (count) { case VECTOR4: { NWCopyVec4Reverse(command, data); NWForwardCurrentCmdBuffer( (REG_COUNT * VECTOR4) * sizeof(f32) ); break; } case MATRIX2x4: { NWCopyMtx24Reverse(command, data); NWForwardCurrentCmdBuffer( (REG_COUNT * MATRIX2x4) * sizeof(f32) ); break; } case MATRIX3x4: { NWCopyMtx34Reverse(command, data); NWForwardCurrentCmdBuffer( (REG_COUNT * MATRIX3x4) * sizeof(f32) ); break; } case MATRIX4x4: { NWCopyMtx44Reverse(command, data); NWForwardCurrentCmdBuffer( (REG_COUNT * MATRIX4x4) * sizeof(f32) ); break; } default: { NW_FATAL_ERROR("Not supported yet.\n"); break; } } } //--------------------------------------------------------------------------- //! @brief ユニフォーム値をGPUへ送信します。 //--------------------------------------------------------------------------- NW_FORCE_INLINE void NWSetUniform4fvEnd() { #if defined(NW_UNIFORM_DUMP) NW_LOG("Set Uniform 4fv End: %d\n"); #endif NWForwardCurrentCmdBuffer( sizeof(f32) ); } NW_FORCE_INLINE void NWSetVertexUniform4fv(u32 index, int count, const f32* data) { NWSetUniform4fv(index, count, data); } NW_FORCE_INLINE void NWSetVertexUniform3fv(u32 index, int count, const f32* data) { NWSetUniform3fv(index, count, data); } NW_FORCE_INLINE void NWSetVertexUniform2fv(u32 index, int count, const f32* data) { NWSetUniform2fv(index, count, data); } NW_FORCE_INLINE void NWSetVertexUniform1fv(u32 index, int count, const f32* data) { NWSetUniform1fv(index, count, data); } NW_FORCE_INLINE void NWSetGeometryUniform4fv(u32 index, int count, const f32* data) { NWSetUniform4fv(index, count, data); } NW_FORCE_INLINE void NWSetGeometryUniform3fv(u32 index, int count, const f32* data) { NWSetUniform3fv(index, count, data); } NW_FORCE_INLINE void NWSetGeometryUniform2fv(u32 index, int count, const f32* data) { NWSetUniform2fv(index, count, data); } NW_FORCE_INLINE void NWSetGeometryUniform1fv(u32 index, int count, const f32* data) { NWSetUniform1fv(index, count, data); } NW_FORCE_INLINE void NWSetVertexUniform4fvBegin(u32 index, int totalCount, int count, const f32* data) { NWSetUniform4fvBegin(index, totalCount, count, data); } NW_FORCE_INLINE void NWSetVertexUniform4fvContinuous(int count, const f32* data) { NWSetUniform4fvContinuous(count, data); } NW_FORCE_INLINE void NWSetVertexUniform4fvEnd() { NWSetUniform4fvEnd(); } NW_FORCE_INLINE void NWSetGeometryUniform4fvBegin(u32 index, int totalCount, int count, const f32* data) { NWSetUniform4fvBegin(index, totalCount, count, data); } NW_FORCE_INLINE void NWSetGeometryUniform4fvContinuous(int count, const f32* data) { NWSetUniform4fvContinuous(count, data); } NW_FORCE_INLINE void NWSetGeometryUniform4fvEnd() { NWSetUniform4fvEnd(); } //--------------------------------------------------------------------------- //! @brief コマンドの保存、デバッグ用クラスです。 //--------------------------------------------------------------------------- class CommandCacheBuilder { public: //--------------------------------------------------------------------------- //! @brief コンストラクタです。 //--------------------------------------------------------------------------- CommandCacheBuilder() : m_StartAddr(NULL), m_EndAddr(NULL) {} //--------------------------------------------------------------------------- //! @brief コマンド保存の開始位置を記録します。 //--------------------------------------------------------------------------- void Begin() { m_StartAddr = NWGetCurrentCmdBuffer(); } //--------------------------------------------------------------------------- //! @brief コマンド保存の終端位置を記録します。 //--------------------------------------------------------------------------- void End() { if (m_StartAddr) { m_EndAddr = NWGetCurrentCmdBuffer(); } } //--------------------------------------------------------------------------- //! @brief コマンドバッファのカレントポインタをBeginの時点に巻き戻します。 //--------------------------------------------------------------------------- void Rollback() { void* current = NWGetCurrentCmdBuffer(); NWBackwardCurrentCmdBuffer( ut::GetOffsetFromPtr(m_StartAddr, current) ); } //--------------------------------------------------------------------------- //! @brief コマンド保存の状態をリセットします。 //--------------------------------------------------------------------------- void Reset() { m_StartAddr = NULL; m_EndAddr = NULL; } //--------------------------------------------------------------------------- //! @brief カレントの保存するべきコマンドのサイズを取得します。 //! //! @return AllocAndCopy 関数で保存されるコマンドサイズです。 //--------------------------------------------------------------------------- s32 GetSize() { if (m_StartAddr && m_EndAddr) { return ut::GetOffsetFromPtr(m_StartAddr, m_EndAddr); } return 0; } //--------------------------------------------------------------------------- //! @brief Begin 関数、End 関数で保存位置を記録した後に、 //! 実際に確保したバッファへのコピーをおこないます。 //--------------------------------------------------------------------------- void* AllocAndCopy(nw::os::IAllocator* allocator = NULL) { s32 size = this->GetSize(); if (size == 0) { return NULL; } void* buffer; if (allocator != NULL) { buffer = allocator->Alloc(size, 4); } else { buffer = CommandCacheManager::Allocate(size); } if (! buffer ) { return NULL; } std::memcpy(buffer, m_StartAddr, size); return buffer; } //--------------------------------------------------------------------------- //! @brief Begin 関数、End 関数で記録された間のコマンドを標準出力に表示します。 //--------------------------------------------------------------------------- void Report(bool detail = false) { if (this->GetSize() == 0) { return; } { u32* addr = reinterpret_cast(m_StartAddr); u32* endAddr = reinterpret_cast(m_EndAddr); NW_LOG("----------\n"); char tmpStr[256]; s32 offset = 0; int count = 0; while (addr < endAddr) { offset += nw::ut::snprintf(&tmpStr[offset], 256 - offset, 256 - offset, "0x%08x, ", *addr); ++addr; ++count; if (count == 4) { NN_LOG("%s\n", tmpStr); offset = 0; count = 0; } } if (offset > 0) { NW_LOG("%s\n", tmpStr); } } if (detail) { struct command_t { // data u32 data : 32; // header u32 addr : 16; u32 be : 4; u32 size : 7; u32 rsv : 4; u32 seq : 1; }; u32* addr = reinterpret_cast(m_StartAddr); u32* endAddr = reinterpret_cast(m_EndAddr); NW_LOG("---- Detail ------\n"); NN_LOG("Size : %d\n", this->GetSize()); while (addr < endAddr) { command_t* command = (command_t*)addr; u32* command_u32 = (u32*)addr; int commandSize = (command->size + 1) & ~1; commandSize += 2; addr += commandSize; NN_LOG("Raw Data:"); for (int i = 0; i < commandSize; i += 2) { if (&command_u32[i] >= endAddr) // 安全のため { commandSize = i - 2; break; } if (i != 0 && i % 8 == 0) { NN_LOG("\n "); } NN_LOG(" 0x%08x, 0x%08x,", command_u32[i], command_u32[i + 1]); } NN_LOG("\n"); NN_LOG("addr : 0x%x\n", command->addr); NN_LOG("be : 0x%x\n", command->be); // バイトイネーブル NN_LOG("size : 0x%x (%d)\n", command->size, command->seq); // データの個数-1 0:シングル >1:バースト NN_LOG("rsv : 0x%x\n", command->rsv); NN_LOG("seq : 0x%x\n", command->seq); NN_LOG("data : 0x%x (%f),\n", command->data, nn::math::U32AsF32(command->data)); for (int i = 2; i < commandSize; i += 2) { if ((i - 2) % 4 == 0) { NN_LOG("\n "); } NN_LOG(" 0x%x (%f), 0x%x (%f),", command_u32[i], nn::math::U32AsF32(command_u32[i]), command_u32[i + 1], nn::math::U32AsF32(command_u32[i + 1])); } if (commandSize != 2) { NN_LOG("\n\n"); } else { NN_LOG("\n"); } } } } private: void* m_StartAddr; void* m_EndAddr; }; } // namespace internal } // namespace gfx } // namespace nw #endif // NW_GFX_COMMAND_UTIL_H_