diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 1c790728f..e6e1465ce 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1457,6 +1457,9 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* } } +extern int sMaxCacheHit; +extern int sCurCacheHit; + void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { if ((avatar->isSelf() && !gAgent.needsRenderAvatar()) || !gMeshRepo.meshRezEnabled()) @@ -1516,44 +1519,57 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) if (buff) { if (sShaderLevel > 0) - { //upload matrix palette to shader - // upload matrix palette to shader - LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = LLSkinningUtil::getMeshJointCount(skin); - LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, avatar); - - stop_glerror(); - - F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT*12]; - - for (U32 i = 0; i < count; ++i) + { + auto& mesh_cache = avatar->getRiggedMatrixCache(); + auto& mesh_id = skin->mMeshID; + auto rigged_matrix_data_iter = find_if(mesh_cache.begin(), mesh_cache.end(), [&mesh_id](decltype(mesh_cache[0]) & entry) { return entry.first == mesh_id; }); + if (rigged_matrix_data_iter != avatar->getRiggedMatrixCache().cend()) { - F32* m = (F32*) mat[i].getF32ptr(); + LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + rigged_matrix_data_iter->second.first, + FALSE, + (GLfloat*)rigged_matrix_data_iter->second.second.data()); + LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(rigged_matrix_data_iter->second.first - 1)); - U32 idx = i*12; - - mp[idx+0] = m[0]; - mp[idx+1] = m[1]; - mp[idx+2] = m[2]; - mp[idx+3] = m[12]; - - mp[idx+4] = m[4]; - mp[idx+5] = m[5]; - mp[idx+6] = m[6]; - mp[idx+7] = m[13]; - - mp[idx+8] = m[8]; - mp[idx+9] = m[9]; - mp[idx+10] = m[10]; - mp[idx+11] = m[14]; + stop_glerror(); } + else + { + // upload matrix palette to shader + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, avatar); - LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, - count, - FALSE, - (GLfloat*) mp); + std::array mp; - LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(count-1)); + for (U32 i = 0; i < count; ++i) + { + F32* m = (F32*)mat[i].getF32ptr(); + + U32 idx = i * 12; + + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + mp[idx + 3] = m[12]; + + mp[idx + 4] = m[4]; + mp[idx + 5] = m[5]; + mp[idx + 6] = m[6]; + mp[idx + 7] = m[13]; + + mp[idx + 8] = m[8]; + mp[idx + 9] = m[9]; + mp[idx + 10] = m[10]; + mp[idx + 11] = m[14]; + } + mesh_cache.emplace_back(std::make_pair( skin->mMeshID, std::make_pair(count, mp) ) ); + LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*)mp.data()); + LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(count - 1)); + } stop_glerror(); } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 8b2690d2d..af647b912 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -81,6 +81,7 @@ #include "llviewerregion.h" #include "lldrawpoolwater.h" #include "lldrawpoolbump.h" +#include "lldrawpoolavatar.h" #include "llwlparammanager.h" #include "llwaterparammanager.h" #include "llpostprocess.h" @@ -255,11 +256,24 @@ static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_CLASS("Class"); static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_BUMP("Bump"); static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_LIST("List"); static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_DELETE("Delete"); + +int sMaxCacheHit = 0; +int sCurCacheHit = 0; + // Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, bool tiling) { LL_RECORD_BLOCK_TIME(FTM_RENDER); + for (auto avatar : LLCharacter::sInstances) + { + LLVOAvatar* avatarp = dynamic_cast(avatar); + if (!avatarp) continue; + if (avatarp->isDead()) continue; + avatarp->clearRiggedMatrixCache(); + } + sCurCacheHit = 0; + if (gWindowResized) { //skip render on frames where window has been resized gGL.flush(); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 5d8442d6f..d8f90a1bc 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -1096,6 +1096,21 @@ protected: // Shared with LLVOAvatarSelf /** Support classes ** ** *******************************************************************************/ + +public: + typedef std::array rigged_matrix_array_t; + typedef std::vector > > rigged_transformation_cache_t; + auto& getRiggedMatrixCache() + { + return mRiggedMatrixDataCache; + } + void clearRiggedMatrixCache() + { + mRiggedMatrixDataCache.clear(); + } +private: + rigged_transformation_cache_t mRiggedMatrixDataCache; + // //Avatar idle timer