From 90ef1ca9f56d136dacb1097ceebead05aa55bf12 Mon Sep 17 00:00:00 2001 From: Rye Mutt <rye@alchemyviewer.org> Date: Wed, 21 Dec 2022 03:25:07 -0500 Subject: [PATCH] Revert "Clean up and crash fixes to mesh repo" This reverts commit 740d34d9e70ef1b7ba5acc05fcdd8e0b2d66efc3. --- indra/newview/llcontrolavatar.cpp | 2 +- indra/newview/llmeshrepository.cpp | 493 +++++++++++++++++++---------- indra/newview/llmeshrepository.h | 17 +- indra/newview/llspatialpartition.h | 2 +- indra/newview/llvovolume.cpp | 38 +-- indra/newview/llvovolume.h | 12 +- 6 files changed, 345 insertions(+), 219 deletions(-) diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index 5523ca494d6..f04b487d120 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -235,7 +235,7 @@ void LLControlAvatar::matchVolumeTransform() #define MATCH_BIND_SHAPE #ifdef MATCH_BIND_SHAPE // MAINT-8671 - based on a patch from Beq Janus - LLConstPointer<LLMeshSkinInfo> skin_info = mRootVolp->getSkinInfo(); + const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo(); if (skin_info) { #ifdef SHOW_DEBUG diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 35cddd39022..0169e74ad72 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1170,9 +1170,8 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) { //could be called from any thread - const LLUUID& mesh_id = mesh_params.getSculptID(); LLMutexLock header_lock(mHeaderMutex); - mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); if (iter != mMeshHeader.end()) { //if we have the header, request LOD byte range header_lock.unlock(); @@ -1187,8 +1186,11 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) else { header_lock.unlock(); + HeaderRequest req(mesh_params); + const LLUUID& mesh_id = mesh_params.getSculptID(); + LLMutexLock lock(mMutex); pending_lod_map::iterator pending = mPendingLOD.find(mesh_id); @@ -1323,104 +1325,100 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int l return handle; } -bool LLMeshRepoThread::getMeshHeaderInfo(const LLUUID& mesh_id, const char* block_name, MeshHeaderInfo& info) -{ //protected by mMutex + +bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry) +{ + if (!mHeaderMutex) { return false; } - LLMutexLock lock(mHeaderMutex); - - ++LLMeshRepository::sMeshRequestCount; + mHeaderMutex->lock(); auto header_it = mMeshHeader.find(mesh_id); if (header_it == mMeshHeader.end()) { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); return false; } - if ((info.mHeaderSize = header_it->second.first) > 0) + ++LLMeshRepository::sMeshRequestCount; + bool ret = true; + U32 header_size = header_it->second.first; + + if (header_size > 0) { - const LLSD& header = header_it->second.second; - const LLSD& block = header[block_name]; - info.mVersion = header["version"].asInteger(); - info.mOffset = info.mHeaderSize + block["offset"].asInteger(); - info.mSize = block["size"].asInteger(); - } - return true; -} + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["skin"]["offset"].asInteger(); + S32 size = header["skin"]["size"].asInteger(); -bool LLMeshRepoThread::loadInfoFromFilesystem(const LLUUID& mesh_id, MeshHeaderInfo& info, boost::function<bool(const LLUUID&, U8*, S32)> fn) -{ - //check cache for mesh skin info - LLFileSystem file(mesh_id, LLAssetType::AT_MESH); - if (file.getSize() >= info.mOffset + info.mSize) - { - auto buffer = std::make_unique<U8[]>(info.mSize); - if (!buffer) - { - LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for mesh data load, size: " << info.mSize << LL_ENDL; - return false; - } - LLMeshRepository::sCacheBytesRead += info.mSize; - ++LLMeshRepository::sCacheReads; - file.seek(info.mOffset); - file.read(buffer.get(), info.mSize); + mHeaderMutex->unlock(); - //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) - bool zero = true; - for (S32 i = 0; i < llmin(info.mSize, S32(1024)) && zero; ++i) + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { - zero = buffer[i] > 0 ? false : true; - } - - if (!zero) - { //attempt to parse - if (fn(mesh_id, buffer.get(), info.mSize)) + //check cache for mesh skin info + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) { - return true; - } - } - } - return false; -} - -bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry) -{ - MeshHeaderInfo info; - if (!getMeshHeaderInfo(mesh_id, "skin", info)) - { - return false; - } + U8* buffer = new(std::nothrow) U8[size]; + if (!buffer) + { + LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL; + return false; + } + LLMeshRepository::sCacheBytesRead += size; + ++LLMeshRepository::sCacheReads; + file.seek(offset); + file.read(buffer, size); - if (info.mHeaderSize > 0 && info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) - { - //check cache for mesh skin info - if (loadInfoFromFilesystem(mesh_id, info, boost::bind(&LLMeshRepoThread::skinInfoReceived, this, _1, _2, _3))) - return true; + //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } - //reading from cache failed for whatever reason, fetch from sim - std::string http_url; - int legacy_cap_version(0); - constructUrl(mesh_id, &http_url, &legacy_cap_version); + if (!zero) + { //attempt to parse + if (skinInfoReceived(mesh_id, buffer, size)) + { + delete[] buffer; + return true; + } + } - if (!http_url.empty()) - { - auto handler = std::make_shared<LLMeshSkinInfoHandler>(mesh_id, info.mOffset, info.mSize); - LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler); - if (LLCORE_HTTP_HANDLE_INVALID == handle) - { - LL_WARNS(LOG_MESH) << "HTTP GET request failed for skin info on mesh " << mID - << ". Reason: " << mHttpStatus.toString() - << " (" << mHttpStatus.toTerseString() << ")" - << LL_ENDL; - return false; + delete[] buffer; } - else if (can_retry) + + //reading from cache failed for whatever reason, fetch from sim + std::string http_url; + int legacy_cap_version(0); + constructUrl(mesh_id, &http_url, &legacy_cap_version); + + if (!http_url.empty()) { - handler->mHttpHandle = handle; - mHttpRequestSet.emplace(std::move(handler)); + auto handler = std::make_shared<LLMeshSkinInfoHandler>(mesh_id, offset, size); + LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler); + if (LLCORE_HTTP_HANDLE_INVALID == handle) + { + LL_WARNS(LOG_MESH) << "HTTP GET request failed for skin info on mesh " << mID + << ". Reason: " << mHttpStatus.toString() + << " (" << mHttpStatus.toTerseString() << ")" + << LL_ENDL; + ret = false; + } + else if(can_retry) + { + handler->mHttpHandle = handle; + mHttpRequestSet.emplace(std::move(handler)); + } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.emplace_back(mesh_id); + } } else { @@ -1435,72 +1433,178 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry) } } else - { - LLMutexLock locker(mMutex); - mSkinUnavailableQ.emplace_back(mesh_id); + { + mHeaderMutex->unlock(); } //early out was not hit, effectively fetched - return true; + return ret; } bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) { - MeshHeaderInfo info; - if (!getMeshHeaderInfo(mesh_id, "physics_convex", info)) + if (!mHeaderMutex) { return false; } - if (info.mHeaderSize > 0 && info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) + mHeaderMutex->lock(); + + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + + ++LLMeshRepository::sMeshRequestCount; + U32 header_size = header_it->second.first; + bool ret = true; + + if (header_size > 0) { - //check cache for mesh physics info - if (loadInfoFromFilesystem(mesh_id, info, boost::bind(&LLMeshRepoThread::decompositionReceived, this, _1, _2, _3))) - return true; + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["physics_convex"]["offset"].asInteger(); + S32 size = header["physics_convex"]["size"].asInteger(); - //reading from cache failed for whatever reason, fetch from sim - std::string http_url; - int legacy_cap_version(0); - constructUrl(mesh_id, &http_url, &legacy_cap_version); + mHeaderMutex->unlock(); - if (!http_url.empty()) + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { - auto handler = std::make_shared<LLMeshDecompositionHandler>(mesh_id, info.mOffset, info.mSize); - LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler); - if (LLCORE_HTTP_HANDLE_INVALID == handle) + //check cache for mesh skin info + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) { - LL_WARNS(LOG_MESH) << "HTTP GET request failed for decomposition mesh " << mID - << ". Reason: " << mHttpStatus.toString() - << " (" << mHttpStatus.toTerseString() << ")" - << LL_ENDL; - return false; + U8* buffer = new(std::nothrow) U8[size]; + if (!buffer) + { + LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL; + return false; + } + LLMeshRepository::sCacheBytesRead += size; + ++LLMeshRepository::sCacheReads; + + file.seek(offset); + file.read(buffer, size); + + //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (decompositionReceived(mesh_id, buffer, size)) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; } - else + + //reading from cache failed for whatever reason, fetch from sim + std::string http_url; + int legacy_cap_version(0); + constructUrl(mesh_id, &http_url, &legacy_cap_version); + + if (!http_url.empty()) { - handler->mHttpHandle = handle; - mHttpRequestSet.insert(handler); + auto handler = std::make_shared<LLMeshDecompositionHandler>(mesh_id, offset, size); + LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler); + if (LLCORE_HTTP_HANDLE_INVALID == handle) + { + LL_WARNS(LOG_MESH) << "HTTP GET request failed for decomposition mesh " << mID + << ". Reason: " << mHttpStatus.toString() + << " (" << mHttpStatus.toTerseString() << ")" + << LL_ENDL; + ret = false; + } + else + { + handler->mHttpHandle = handle; + mHttpRequestSet.insert(handler); + } } } } + else + { + mHeaderMutex->unlock(); + } //early out was not hit, effectively fetched - return true; + return ret; } bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) { - MeshHeaderInfo info; - if (!getMeshHeaderInfo(mesh_id, "physics_mesh", info)) + if (!mHeaderMutex) { return false; } - if (info.mHeaderSize > 0) + mHeaderMutex->lock(); + + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + + ++LLMeshRepository::sMeshRequestCount; + U32 header_size = header_it->second.first; + bool ret = true; + + if (header_size > 0) { - if (info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["physics_mesh"]["offset"].asInteger(); + S32 size = header["physics_mesh"]["size"].asInteger(); + + mHeaderMutex->unlock(); + + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { - if (loadInfoFromFilesystem(mesh_id, info, boost::bind(&LLMeshRepoThread::physicsShapeReceived, this, _1, _2, _3))) - return true; + //check cache for mesh physics shape info + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + ++LLMeshRepository::sCacheReads; + file.seek(offset); + U8* buffer = new(std::nothrow) U8[size]; + if (!buffer) + { + LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for physics shape, size: " << size << LL_ENDL; + return false; + } + file.read(buffer, size); + + //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (physicsShapeReceived(mesh_id, buffer, size) == MESH_OK) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; + } //reading from cache failed for whatever reason, fetch from sim std::string http_url; @@ -1509,15 +1613,15 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) if (!http_url.empty()) { - auto handler = std::make_shared<LLMeshPhysicsShapeHandler>(mesh_id, info.mOffset, info.mSize); - LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler); + auto handler = std::make_shared<LLMeshPhysicsShapeHandler>(mesh_id, offset, size); + LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) { LL_WARNS(LOG_MESH) << "HTTP GET request failed for physics shape on mesh " << mID << ". Reason: " << mHttpStatus.toString() << " (" << mHttpStatus.toTerseString() << ")" << LL_ENDL; - return false; + ret = false; } else { @@ -1531,9 +1635,13 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) physicsShapeReceived(mesh_id, NULL, 0); } } + else + { + mHeaderMutex->unlock(); + } //early out was not hit, effectively fetched - return true; + return ret; } //static @@ -1583,11 +1691,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c file.read(buffer, bytes); if (headerReceived(mesh_params, buffer, bytes) == MESH_OK) { -#ifdef SHOW_DEBUG - std::string mid; - mesh_params.getSculptID().toString(mid); - LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh header for ID " << mid << " - was retrieved from the cache." << LL_ENDL; -#endif // Found mesh in cache return true; } @@ -1602,12 +1705,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c if (!http_url.empty()) { -#ifdef SHOW_DEBUG - std::string mid; - mesh_params.getSculptID().toString(mid); - LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh header for ID " << mid << " - was retrieved from the simulator." << LL_ENDL; -#endif - //grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits //within the first 4KB //NOTE -- this will break of headers ever exceed 4KB @@ -1635,20 +1732,70 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c //return false if failed to get mesh lod. bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, bool can_retry) { - LLUUID mesh_id = mesh_params.getSculptID(); - MeshHeaderInfo info; - - if (!getMeshHeaderInfo(mesh_id, header_lod[lod].c_str(), info)) + if (!mHeaderMutex) { return false; } - - if (info.mHeaderSize > 0) + + const LLUUID& mesh_id = mesh_params.getSculptID(); + + mHeaderMutex->lock(); + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + ++LLMeshRepository::sMeshRequestCount; + bool retval = true; + + U32 header_size = header_it->second.first; + if (header_size > 0) { - if(info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header[header_lod[lod]]["offset"].asInteger(); + S32 size = header[header_lod[lod]]["size"].asInteger(); + mHeaderMutex->unlock(); + + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) { - if (loadInfoFromFilesystem(mesh_id, info, boost::bind(&LLMeshRepoThread::lodReceived, this, mesh_params, lod, _2, _3 ))) - return true; + + //check cache for mesh asset + LLFileSystem file(mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + U8* buffer = new(std::nothrow) U8[size]; + if (!buffer) + { + LL_WARNS_ONCE(LOG_MESH) << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL; + // todo: for now it will result in indefinite constant retries, should result in timeout + // or in retry-count and disabling mesh. (but usually viewer is beyond saving at this point) + return false; + } + LLMeshRepository::sCacheBytesRead += size; + ++LLMeshRepository::sCacheReads; + file.seek(offset); + file.read(buffer, size); + + //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (lodReceived(mesh_params, lod, buffer, size) == MESH_OK) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; + } //reading from cache failed for whatever reason, fetch from sim std::string http_url; @@ -1657,20 +1804,15 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, if (!http_url.empty()) { -#if SHOW_DEBUG - std::string mid; - mesh_id.toString(mid); - LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh body for ID " << mid << " - was retrieved from the simulator." << LL_ENDL; -#endif - auto handler = std::make_shared<LLMeshLODHandler>(mesh_params, lod, info.mOffset, info.mSize); - LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler); + auto handler = std::make_shared<LLMeshLODHandler>(mesh_params, lod, offset, size); + LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) { LL_WARNS(LOG_MESH) << "HTTP GET request failed for LOD on mesh " << mID << ". Reason: " << mHttpStatus.toString() << " (" << mHttpStatus.toTerseString() << ")" << LL_ENDL; - return false; + retval = false; } else if (can_retry) { @@ -1701,7 +1843,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, mHeaderMutex->unlock(); } - return true; + return retval; } EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size) @@ -1758,6 +1900,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes LLMeshRepository::sCacheBytesHeaders += header_size; } + LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time. //check for pending requests @@ -1785,6 +1928,7 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p } LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); + if (volume->unpackVolumeFaces(data, data_size)) { if (volume->getNumFaces() > 0) @@ -2736,7 +2880,7 @@ void LLMeshRepoThread::notifyLoadedMeshes() // Process the elements free of the lock for (const auto& mesh : loaded_queue) { - if (mesh.mVolume && mesh.mVolume->getNumVolumeFaces() > 0) + if (mesh.mVolume->getNumVolumeFaces() > 0) { gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); } @@ -3495,13 +3639,13 @@ void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) { for (auto& param : lod) { - param.second.erase(vobj); + vector_replace_with_last(param.second, vobj); } } for (auto& skin_pair : mLoadingSkins) { - skin_pair.second.erase(vobj); + vector_replace_with_last(skin_pair.second, vobj); } } @@ -3520,20 +3664,18 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - const auto& mesh_id = mesh_params.getSculptID(); - mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params.getSculptID()); if (iter != mLoadingMeshes[detail].end()) { //request pending for this mesh, append volume id to list - auto& obj_set = iter->second; - auto it = obj_set.find(vobj); - if (it == obj_set.end()) { - obj_set.insert(vobj); + auto it = std::find(iter->second.begin(), iter->second.end(), vobj); + if (it == iter->second.end()) { + iter->second.push_back(vobj); } } else { //first request for this mesh - mLoadingMeshes[detail][mesh_id].insert(vobj); + mLoadingMeshes[detail][mesh_params.getSculptID()].push_back(vobj); mPendingRequests.emplace_back(mesh_params, detail); LLMeshRepository::sLODPending++; } @@ -3868,7 +4010,7 @@ void LLMeshRepository::notifyLoadedMeshes() void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info) { - mSkinMap[info->mMeshID] = info; // Cache into LLPointer + auto pair = mSkinMap.emplace(info->mMeshID, info); // Cache into LLPointer // Alternative: We can get skin size from header sCacheBytesSkins += info->sizeBytes(); @@ -3879,7 +4021,7 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info) { if (vobj) { - vobj->notifySkinInfoLoaded(info); + vobj->notifySkinInfoLoaded(((*pair.first).second)); } } mLoadingSkins.erase(iter); @@ -4005,33 +4147,32 @@ LLPointer<LLMeshSkinInfo> LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, L if (mesh_id.notNull()) { skin_map::iterator iter = mSkinMap.find(mesh_id); - if (iter != mSkinMap.end()) - { - return iter->second; - } - - //no skin info known about given mesh, try to fetch it - if (requesting_obj != nullptr) - { - LLMutexLock lock(mMeshMutex); - //add volume to list of loading meshes - skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); + if (iter != mSkinMap.end()) + { + return iter->second; + } + + //no skin info known about given mesh, try to fetch it + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); if (iter != mLoadingSkins.end()) { //request pending for this mesh, append volume id to list - auto& obj_set = iter->second; - auto it = obj_set.find(requesting_obj); - if (it == obj_set.end()) { - obj_set.insert(requesting_obj); + auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj); + if (it == iter->second.end()) { + iter->second.push_back(requesting_obj); } } else { //first request for this mesh - mLoadingSkins[mesh_id].insert(requesting_obj); - mPendingSkinRequests.push(mesh_id); - } - } - } + mLoadingSkins[mesh_id].push_back(requesting_obj); + mPendingSkinRequests.push(mesh_id); + } + } + } + return nullptr; } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 64896942e84..f48797b9190 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -283,16 +283,6 @@ class LLMeshRepoThread final : public LLThread }; - struct MeshHeaderInfo - { - MeshHeaderInfo() - : mHeaderSize(0), mVersion(0), mOffset(-1), mSize(0) {} - U32 mHeaderSize; - U32 mVersion; - S32 mOffset; - S32 mSize; - }; - ///////// // In flight queues ///////// @@ -373,9 +363,6 @@ class LLMeshRepoThread final : public LLThread EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size); bool hasPhysicsShapeInHeader(const LLUUID& mesh_id); - bool getMeshHeaderInfo(const LLUUID& mesh_id, const char* block_name, MeshHeaderInfo& info); - bool loadInfoFromFilesystem(const LLUUID& mesh_id, MeshHeaderInfo& info, boost::function<bool(const LLUUID&, U8*, S32)> fn); - void notifyLoadedMeshes(); // Only call from main thread. S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); @@ -646,7 +633,7 @@ class LLMeshRepository static void metricsProgress(unsigned int count); static void metricsUpdate(); - typedef boost::unordered_map<LLUUID, boost::unordered_set<LLVOVolume*> > mesh_load_map; + typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map; mesh_load_map mLoadingMeshes[4]; typedef boost::unordered_flat_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map; @@ -660,7 +647,7 @@ class LLMeshRepository std::vector<LLMeshRepoThread::LODRequest> mPendingRequests; //list of mesh ids awaiting skin info - typedef boost::unordered_map<LLUUID, boost::unordered_set<LLVOVolume*> > skin_load_map; + typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map; skin_load_map mLoadingSkins; //list of mesh ids that need to send skin info fetch requests diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 6c50893d7ea..a5db551dd84 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -118,7 +118,7 @@ class LLDrawInfo : public LLRefCount U8 mDiffuseAlphaMode; bool mSelected; LLPointer<LLVOAvatar> mAvatar = nullptr; - LLPointer<LLMeshSkinInfo> mSkinInfo = nullptr; + LLMeshSkinInfo* mSkinInfo = nullptr; struct CompareTexture diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 6cc435420a5..926c787e841 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -234,7 +234,10 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mColorChanged = FALSE; mSpotLightPriority = 0.f; + mSkinInfoFailed = false; mSkinInfo = NULL; + mSkinRenderMatrixJointCount = 0; + mSkinLastRenderFrame = 0; mMediaImplList.resize(getNumTEs()); mLastFetchedMediaVersion = -1; @@ -254,10 +257,7 @@ LLVOVolume::~LLVOVolume() mSkinInfo = nullptr; - //if(mMeshDataInFlight || mSkinInfoInFlight) - { - gMeshRepo.unregisterMesh(this); - } + gMeshRepo.unregisterMesh(this); if(!mMediaImplList.empty()) { @@ -1117,6 +1117,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID()) { mSkinInfo = NULL; + mSkinInfoFailed = false; } if (!getVolume()->isMeshAssetLoaded()) @@ -1129,12 +1130,12 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo } } - if (!mSkinInfo) + if (!mSkinInfo && !hasSkinInfoFailed()) { - const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this); - if (skin_info) + mSkinInfo = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this); + if (mSkinInfo) { - notifySkinInfoLoaded(skin_info); + notifySkinInfoLoaded(mSkinInfo); } } } @@ -1170,6 +1171,7 @@ void LLVOVolume::updateSculptTexture() mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } + mSkinInfoFailed = false; mSkinInfo = NULL; } else @@ -1225,29 +1227,17 @@ void LLVOVolume::notifyMeshLoaded() updateVisualComplexity(); } -void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin) +void LLVOVolume::notifySkinInfoLoaded(LLMeshSkinInfo* skin) { + mSkinInfoFailed = false; mSkinInfo = skin; - mSculptChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); - LLVOAvatar *av = getAvatar(); - if (av && !isAnimatedObject()) - { - av->addAttachmentOverridesForObject(this); - av->notifyAttachmentMeshLoaded(); - } - LLControlAvatar *cav = getControlAvatar(); - if (cav && isAnimatedObject()) - { - cav->addAttachmentOverridesForObject(this); - cav->notifyAttachmentMeshLoaded(); - } - updateVisualComplexity(); + notifyMeshLoaded(); } void LLVOVolume::notifySkinInfoUnavailable() { + mSkinInfoFailed = true; mSkinInfo = nullptr; } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 30c9e4d4bc6..764d398df53 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -357,7 +357,7 @@ class LLVOVolume final : public LLViewerObject void updateVisualComplexity(); void notifyMeshLoaded(); - void notifySkinInfoLoaded(const LLMeshSkinInfo* skin); + void notifySkinInfoLoaded(LLMeshSkinInfo* skin); void notifySkinInfoUnavailable(); // Returns 'true' iff the media data for this object is in flight @@ -442,7 +442,15 @@ class LLVOVolume final : public LLViewerObject bool mResetDebugText; LLPointer<LLRiggedVolume> mRiggedVolume; - LLConstPointer<LLMeshSkinInfo> mSkinInfo; + + bool hasSkinInfoFailed() const { return mSkinInfoFailed; } + + bool mSkinInfoFailed; + LLPointer<LLMeshSkinInfo> mSkinInfo; + std::unique_ptr <LLMatrix4a[]> mSkinMatrixCache; + std::unique_ptr <F32[]> mSkinRenderMatrixCache; + U32 mSkinRenderMatrixJointCount; + U32 mSkinLastRenderFrame; // statics public: -- GitLab