From a83a4811b51472b5f760861b6a8acde5fc3bd43b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Nov 2022 22:45:20 +0200 Subject: SL-18518 Move json to material work to background thread --- indra/newview/llgltfmateriallist.cpp | 164 ++++++++++++++++++++++------------- indra/newview/llgltfmateriallist.h | 11 +++ 2 files changed, 113 insertions(+), 62 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 8e184c719d..c18988ef15 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -271,92 +271,132 @@ void LLGLTFMaterialList::flushModifyMaterialQueue(void(*done_callback)(bool)) sModifyQueue.clear(); } -LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) +class AssetLoadUserData { - LL_PROFILE_ZONE_SCOPED; - uuid_mat_map_t::iterator iter = mList.find(id); - if (iter == mList.end()) +public: + AssetLoadUserData() {} + tinygltf::Model mModelIn; + LLPointer mMaterial; +}; + +void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::EType asset_type, void* user_data, S32 status, LLExtStat ext_status) +{ + LL_PROFILE_ZONE_NAMED("gltf asset callback"); + AssetLoadUserData* asset_data = (AssetLoadUserData*)user_data; + + if (status != LL_ERR_NOERR) + { + LL_WARNS() << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL; + asset_data->mMaterial->mFetching = false; + delete asset_data; + } + else { - LL_PROFILE_ZONE_NAMED("gltf fetch") - LLFetchedGLTFMaterial* mat = new LLFetchedGLTFMaterial(); - mList[id] = mat; - if (!mat->mFetching) - { - // if we do multiple getAssetData calls, - // some will get distched, messing ref counter - // Todo: get rid of mat->ref() - mat->mFetching = true; - mat->ref(); + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); - gAssetStorage->getAssetData(id, LLAssetType::AT_MATERIAL, - [=](const LLUUID& id, LLAssetType::EType asset_type, void* user_data, S32 status, LLExtStat ext_status) + typedef std::pair return_data_t; + + main_queue->postTo( + general_queue, + [id, asset_type, asset_data]() // Work done on general queue + { + std::vector buffer; { - LL_PROFILE_ZONE_NAMED("gltf asset callback"); - if (status) + LL_PROFILE_ZONE_NAMED("gltf read asset"); + LLFileSystem file(id, asset_type, LLFileSystem::READ); + auto size = file.getSize(); + if (!size) { - LL_WARNS() << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL; + return false; } - std::vector buffer; + buffer.resize(size); + file.read((U8*)&buffer[0], buffer.size()); + } - { - LL_PROFILE_ZONE_NAMED("gltf read asset"); - LLFileSystem file(id, asset_type, LLFileSystem::READ); - auto size = file.getSize(); - if (!size) - { - LL_DEBUGS() << "Zero size material." << LL_ENDL; - mat->mFetching = false; - mat->unref(); - return; - } + { + LL_PROFILE_ZONE_NAMED("gltf deserialize asset"); + LLSD asset; + // read file into buffer + std::istrstream str(&buffer[0], buffer.size()); - buffer.resize(size); - file.read((U8*)&buffer[0], buffer.size()); - } - + if (LLSDSerialize::deserialize(asset, str, buffer.size())) { - LL_PROFILE_ZONE_NAMED("gltf deserialize asset"); - - LLSD asset; - - // read file into buffer - std::istrstream str(&buffer[0], buffer.size()); - - if (LLSDSerialize::deserialize(asset, str, buffer.size())) + if (asset.has("version") && asset["version"] == "1.0") { - if (asset.has("version") && asset["version"] == "1.0") + if (asset.has("type") && asset["type"].asString() == "GLTF 2.0") { - if (asset.has("type") && asset["type"].asString() == "GLTF 2.0") + if (asset.has("data") && asset["data"].isString()) { - if (asset.has("data") && asset["data"].isString()) - { - std::string data = asset["data"]; + std::string data = asset["data"]; + + std::string warn_msg, error_msg; - std::string warn_msg, error_msg; + LL_PROFILE_ZONE_SCOPED; + tinygltf::TinyGLTF gltf; - if (!mat->fromJSON(data, warn_msg, error_msg)) - { - LL_WARNS() << "Failed to decode material asset: " << LL_ENDL; - LL_WARNS() << warn_msg << LL_ENDL; - LL_WARNS() << error_msg << LL_ENDL; - } + if (!gltf.LoadASCIIFromString(&asset_data->mModelIn, &error_msg, &warn_msg, data.c_str(), data.length(), "")) + { + LL_WARNS() << "Failed to decode material asset: " + << LL_NEWLINE + << warn_msg + << LL_NEWLINE + << error_msg + << LL_ENDL; + return false; } + return true; } } } - else - { - LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL; - } } + else + { + LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL; + } + } + + return false; + }, + [id, asset_data](bool result) // Callback to main thread + mutable { + + if (result) + { + asset_data->mMaterial->setFromModel(asset_data->mModelIn, 0/*only one index*/); + } + else + { + LL_DEBUGS() << "Failed to get material " << id << LL_ENDL; + } + asset_data->mMaterial->mFetching = false; + delete asset_data; + }); + } +} + +LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) +{ + LL_PROFILE_ZONE_SCOPED; + uuid_mat_map_t::iterator iter = mList.find(id); + if (iter == mList.end()) + { + LL_PROFILE_ZONE_NAMED("gltf fetch") + LLFetchedGLTFMaterial* mat = new LLFetchedGLTFMaterial(); + mList[id] = mat; + + if (!mat->mFetching) + { + mat->mFetching = true; + + AssetLoadUserData *user_data = new AssetLoadUserData(); + user_data->mMaterial = mat; - mat->mFetching = false; - mat->unref(); - }, nullptr); + gAssetStorage->getAssetData(id, LLAssetType::AT_MATERIAL, onAssetLoadComplete, (void*)user_data); } return mat; diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index e035d2108d..2dae11d2ca 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -26,6 +26,8 @@ #pragma once +#include "llassettype.h" +#include "llextendedstatus.h" #include "llfetchedgltfmaterial.h" #include "llgltfmaterial.h" #include "llpointer.h" @@ -69,6 +71,15 @@ public: void queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFMaterial* override_data); void applyQueuedOverrides(LLViewerObject* obj); + +protected: + static void onAssetLoadComplete( + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, + S32 status, + LLExtStat ext_status); + private: typedef std::unordered_map > uuid_mat_map_t; uuid_mat_map_t mList; -- cgit v1.2.3