Skip to content

Commit

Permalink
#3488 Part of skin info processing out of mesh thread
Browse files Browse the repository at this point in the history
Skin info parsing is expensive, offload to thread pool
  • Loading branch information
akleshchev committed Feb 4, 2025
1 parent c010880 commit c331e00
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 10 deletions.
83 changes: 74 additions & 9 deletions indra/newview/llmeshrepository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,8 +875,8 @@ LLMeshRepoThread::LLMeshRepoThread()

// Lod processing is expensive due to the number of requests
// and a need to do expensive cacheOptimize().
mLodThreadPool.reset(new LL::ThreadPool("MeshLodProcessing", 2));
mLodThreadPool->start();
mMeshThreadPool.reset(new LL::ThreadPool("MeshLodProcessing", 2));
mMeshThreadPool->start();
}


Expand Down Expand Up @@ -1473,9 +1473,18 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
LLFileSystem file(mesh_id, LLAssetType::AT_MESH);
if (in_cache && file.getSize() >= disk_ofset + size)
{
U8* buffer = getDiskCacheBuffer(size);
U8* buffer = new(std::nothrow) U8[size];
if (!buffer)
{
LL_WARNS(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL;

// Not sure what size is reasonable for skin info,
// but if 20MB allocation failed, we definetely have issues
const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
if (size < MAX_SIZE)
{
LLAppViewer::instance()->outOfMemorySoftQuit();
} // else ignore failures for anomalously large data
LLMutexLock locker(mLoadedMutex);
mSkinUnavailableQ.emplace_back(mesh_id);
return true;
Expand All @@ -1493,12 +1502,68 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
}

if (!zero)
{ //attempt to parse
if (skinInfoReceived(mesh_id, buffer, size))
{
//attempt to parse
bool posted = mMeshThreadPool->getQueue().post(
[mesh_id, buffer, size]
()
{
if (!gMeshRepo.mThread->skinInfoReceived(mesh_id, buffer, size))
{
// either header is faulty or something else overwrote the cache
S32 header_size = 0;
U32 header_flags = 0;
{
LL_DEBUGS(LOG_MESH) << "Mesh header for ID " << mesh_id << " cache mismatch." << LL_ENDL;

LLMutexLock lock(gMeshRepo.mThread->mHeaderMutex);

auto header_it = gMeshRepo.mThread->mMeshHeader.find(mesh_id);
if (header_it != gMeshRepo.mThread->mMeshHeader.end())
{
LLMeshHeader& header = header_it->second;
// for safety just mark everything as missing
header.mSkinInCache = false;
header.mPhysicsConvexInCache = false;
header.mPhysicsMeshInCache = false;
for (S32 i = 0; i < LLModel::NUM_LODS; ++i)
{
header.mLodInCache[i] = false;
}
header_size = header.mHeaderSize;
header_flags = header.getFlags();
}
}

if (header_size > 0)
{
LLFileSystem file(mesh_id, LLAssetType::AT_MESH, LLFileSystem::READ_WRITE);
if (file.getMaxSize() >= CACHE_PREAMBLE_SIZE)
{
write_preamble(file, header_size, header_flags);
}
}

{
LLMutexLock lock(gMeshRepo.mThread->mMutex);
UUIDBasedRequest req(mesh_id);
gMeshRepo.mThread->mSkinRequests.push_back(req);
}
}
delete[] buffer;
});
if (posted)
{
// lambda owns buffer
return true;
}
else if (skinInfoReceived(mesh_id, buffer, size))
{
delete[] buffer;
return true;
}
}
delete[] buffer;
}

//reading from cache failed for whatever reason, fetch from sim
Expand Down Expand Up @@ -1938,7 +2003,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
if (!zero)
{
//attempt to parse
bool posted = mLodThreadPool->getQueue().post(
bool posted = mMeshThreadPool->getQueue().post(
[mesh_params, mesh_id, lod, buffer, size]
()
{
Expand Down Expand Up @@ -3733,7 +3798,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
&& ((data != NULL) == (data_size > 0))) // if we have data but no size or have size but no data, something is wrong
{
LLMeshHandlerBase::ptr_t shrd_handler = shared_from_this();
bool posted = gMeshRepo.mThread->mLodThreadPool->getQueue().post(
bool posted = gMeshRepo.mThread->mMeshThreadPool->getQueue().post(
[shrd_handler, data, data_size]
()
{
Expand All @@ -3750,7 +3815,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
else
{
// mesh thread dies later than event queue, so this is normal
LL_INFOS_ONCE(LOG_MESH) << "Failed to post work into mLodThreadPool" << LL_ENDL;
LL_INFOS_ONCE(LOG_MESH) << "Failed to post work into mMeshThreadPool" << LL_ENDL;
processLod(data, data_size);
}
}
Expand Down Expand Up @@ -4038,7 +4103,7 @@ void LLMeshRepository::shutdown()
}

mThread->mSignal->broadcast();
mThread->mLodThreadPool->close();
mThread->mMeshThreadPool->close();

while (!mThread->isStopped())
{
Expand Down
2 changes: 1 addition & 1 deletion indra/newview/llmeshrepository.h
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ class LLMeshRepoThread : public LLThread
// workqueue for processing generic requests
LL::WorkQueue mWorkQueue;
// lods have their own thread due to costly cacheOptimize() calls
std::unique_ptr<LL::ThreadPool> mLodThreadPool;
std::unique_ptr<LL::ThreadPool> mMeshThreadPool;

// llcorehttp library interface objects.
LLCore::HttpStatus mHttpStatus;
Expand Down

0 comments on commit c331e00

Please sign in to comment.