diff options
| -rw-r--r-- | indra/newview/CMakeLists.txt | 8 | ||||
| -rwxr-xr-x | indra/newview/llviewerregion.cpp | 12 | ||||
| -rw-r--r-- | indra/newview/llvocache.cpp | 184 | ||||
| -rw-r--r-- | indra/newview/llvocache.h | 3 | ||||
| -rw-r--r-- | indra/newview/tests/lldir_stub.cpp | 30 | ||||
| -rw-r--r-- | indra/newview/tests/llvieweroctree_stub.cpp | 86 | ||||
| -rw-r--r-- | indra/newview/tests/llvocache_test.cpp | 146 | 
7 files changed, 435 insertions, 34 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1588f16f07..3271de72c9 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2383,6 +2383,7 @@ if (LL_TESTS)  #    llremoteparcelrequest.cpp      llviewerhelputil.cpp      llversioninfo.cpp +    llvocache.cpp      llworldmap.cpp      llworldmipmap.cpp    ) @@ -2396,6 +2397,13 @@ if (LL_TESTS)      #llviewertexturelist.cpp    ) +  set_source_files_properties( +    llvocache.cpp +    PROPERTIES +    LL_TEST_ADDITIONAL_SOURCE_FILES  +    ../llmessage/lldatapacker.cpp +  ) +    set(test_libs      ${LLCOMMON_LIBRARIES}      ${JSONCPP_LIBRARIES} diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e3ac1767fb..afe48f01b5 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -785,7 +785,7 @@ void LLViewerRegion::loadObjectCache()  	if(LLVOCache::instanceExists())  	{          LLVOCache & vocache = LLVOCache::instance(); -		vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap)  ; +		vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap);          vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesJson);  		if (mImpl->mCacheMap.empty()) @@ -814,7 +814,8 @@ void LLViewerRegion::saveObjectCache()  		bool removal_enabled = sVOCacheCullingEnabled && (mRegionTimer.getElapsedTimeF32() > start_time_threshold); //allow to remove invalid objects from object cache file.          LLVOCache & instance = LLVOCache::instance(); -		instance.writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled)  ; + +        instance.writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled);          instance.writeGenericExtrasToCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesJson, mCacheDirty, removal_enabled);  		mCacheDirty = FALSE;  	} @@ -822,6 +823,7 @@ void LLViewerRegion::saveObjectCache()  	// Map of LLVOCacheEntry takes time to release, store map for cleanup on idle  	sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end());  	mImpl->mCacheMap.clear(); +    // TODO - probably need to do the same for overrides cache  }  void LLViewerRegion::sendMessage() @@ -2646,6 +2648,8 @@ void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry      LLViewerObject * obj = gObjectList.findObject(object_id);      if (obj != nullptr)      { +        llassert(obj->getRegion() == this); +          U32 local_id = obj->getLocalID();          mImpl->mGLTFOverridesJson[local_id] = override_data; @@ -3547,4 +3551,8 @@ void LLViewerRegion::loadCacheMiscExtras(U32 local_id, LLVOCacheEntry * entry, U      {          LLGLTFMaterialList::loadCacheOverrides(iter->second);      } +    else +    { +        LL_DEBUGS("GLTF") << "cache miss for handle: " << mHandle << " local_id:" << local_id << LL_ENDL; +    }  } diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index cb75426cce..21a6a2950e 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -26,15 +26,13 @@  #include "llviewerprecompiledheaders.h"  #include "llvocache.h" -#include "llerror.h"  #include "llregionhandle.h"  #include "llviewercontrol.h"  #include "llviewerobjectlist.h"  #include "lldrawable.h"  #include "llviewerregion.h" -#include "pipeline.h"  #include "llagentcamera.h" -#include "llmemory.h" +#include "llsdserialize.h"  //static variables  U32 LLVOCacheEntry::sMinFrameRange = 0; @@ -65,12 +63,12 @@ bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data)          return false;      } -    if (data.has("region_handle_low") && data.has("region_handle_high")) +    if (data.has("region_handle_x") && data.has("region_handle_y"))      {          // TODO start requiring this once server sends this for all messages -        U64 region_handle_low = data["region_handle_low"].asInteger(); -        U64 region_handle_high = data["region_handle_high"].asInteger(); -        mRegionHandle = (region_handle_low & 0x00000000ffffffffUL) || (region_handle_high << 32); +        U32 region_handle_y = data["region_handle_y"].asInteger(); +        U32 region_handle_x = data["region_handle_x"].asInteger(); +        mRegionHandle = to_region_handle(region_handle_x, region_handle_y);          mHasRegionHandle = true;      }      else @@ -99,29 +97,31 @@ bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data)                  mSides[side_idx] = gltf_json[i].asString();              }          } +        else +        { +            LL_WARNS_IF(sides.size() != 0, "GLTF") << "broken override cache entry" << LL_ENDL; +        }      }      return true;  } -LLSD LLGLTFOverrideCacheEntry::toLLSD() +LLSD LLGLTFOverrideCacheEntry::toLLSD() const  { -    llassert(false); // "Function not tested!!! -      LLSD data;      if (mHasRegionHandle)      { -        data["region_handle_low"] = LLSD::Integer(mRegionHandle & 0x00000000ffffffffUL); -        data["region_handle_high"] = LLSD::Integer(mRegionHandle >> 32); +        U32 region_handle_x, region_handle_y; +        from_region_handle(mRegionHandle, ®ion_handle_x, ®ion_handle_y); +        data["region_handle_y"] = LLSD::Integer(region_handle_y); +        data["region_handle_x"] = LLSD::Integer(region_handle_x);      }      data["object_id"] = mObjectId; -    std::map<S32, std::string>::const_iterator iter = mSides.begin(); -    std::map<S32, std::string>::const_iterator end = mSides.end(); -    while (iter != end) +    for (auto const & side : mSides)      { -        data["sides"].append(LLSD::Integer(iter->first)); -        data["sides"].append(iter->second); +        data["sides"].append(LLSD::Integer(side.first)); +        data["gltf_json"].append(side.second);      }      return data; @@ -425,6 +425,7 @@ S32 LLVOCacheEntry::writeToBuffer(U8 *data_buffer) const      return ENTRY_HEADER_SIZE + size;  } +#ifndef LL_TEST  //static   void LLVOCacheEntry::updateDebugSettings()  { @@ -477,6 +478,7 @@ void LLVOCacheEntry::updateDebugSettings()      const U32 clamped_frames = inv_obj_time ? llclamp((U32) inv_obj_time, MIN_FRAMES, MAX_FRAMES) : MAX_FRAMES; // [10, 64], with zero => 64      sMinFrameRange = MIN_FRAMES + ((clamped_frames - MIN_FRAMES) * adjust_factor);  } +#endif // LL_TEST  //static   F32 LLVOCacheEntry::getSquaredPixelThreshold(bool is_front) @@ -948,6 +950,7 @@ void LLVOCachePartition::selectBackObjects(LLCamera &camera, F32 pixel_threshold  	return;  } +#ifndef LL_TEST  S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion)  {  	static LLCachedControl<bool> use_object_cache_occlusion(gSavedSettings,"UseObjectCacheOcclusion"); @@ -1014,6 +1017,7 @@ S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion)  	}  	return 1;  } +#endif // LL_TEST  void LLVOCachePartition::setCullHistory(BOOL has_new_object)  { @@ -1087,8 +1091,9 @@ void LLVOCachePartition::removeOccluder(LLVOCacheGroup* group)  //-------------------------------------------------------------------  //LLVOCache  //------------------------------------------------------------------- -// Format string used to construct filename for the object cache +// Format strings used to construct filename for the object cache  static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; +static const char OBJECT_CACHE_EXTRAS_FILENAME[] = "objects_%d_%d_extras.slec";  const U32 MAX_NUM_OBJECT_ENTRIES = 128 ;  const U32 MIN_ENTRIES_TO_PURGE = 16 ; @@ -1101,9 +1106,12 @@ LLVOCache::LLVOCache(bool read_only) :  	mInitialized(false),  	mReadOnly(read_only),  	mNumEntries(0), -	mCacheSize(1) +	mCacheSize(1), +    mEnabled(true)  { +#ifndef LL_TEST  	mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); +#endif  	mLocalAPRFilePoolp = new LLVolatileAPRPool() ;  } @@ -1280,6 +1288,15 @@ void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename)  	return ;  } +std::string LLVOCache::getObjectCacheExtrasFilename(U64 handle) +{ +    U32 region_x, region_y; + +    grid_from_region_handle(handle, ®ion_x, ®ion_y); +    return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname, +               llformat(OBJECT_CACHE_EXTRAS_FILENAME, region_x, region_y)); +} +  void LLVOCache::removeFromCache(HeaderEntryInfo* entry)  {  	if(mReadOnly) @@ -1507,7 +1524,78 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca  void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map)  { -    LL_DEBUGS() << "TODO" << LL_ENDL; +    if(!mEnabled) +    { +        LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; +        return ; +    } +    llassert_always(mInitialized); + +    handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; +    if(iter == mHandleEntryMap.end()) //no cache +    { +        LL_WARNS() << "No handle map entry for " << handle << LL_ENDL; +        return; +    } + +    std::string filename(getObjectCacheExtrasFilename(handle)); +    llifstream in(filename, std::ios::in | std::ios::binary); + +    std::string line; +    std::getline(in, line); +    if(!in.good()) { +        LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; +        return; +    } + +    if(!LLUUID::validate(line)) +    { +        LL_WARNS() << "Failed reading extras cache for handle" << handle << ". invalid uuid line: '" << line << "'" << LL_ENDL; +        return; +    } + +    LLUUID cache_id(line); +    if(cache_id != id) +    { +        LL_INFOS() << "Cache ID doesn't match for this region, discarding" << LL_ENDL; +        return; +    } + +    U32 num_entries;  // if removal was enabled during write num_entries might be wrong +    std::getline(in, line); +    if(!in.good()) { +        LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; +        return; +    } +    try { +        num_entries = std::stol(line); +    } +    catch(std::logic_error &excp)  // either invalid_argument or out_of_range +    { +        LL_WARNS() << "Failed reading extras cache for handle " << handle << ". unreadable num_entries" << LL_ENDL; +        return; +    } + +    LL_DEBUGS("GLTF") << "Beginning reading extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL; + +    LLSD entry_llsd; +    for (U32 i = 0; i < num_entries && !in.eof(); i++) +    { +        static const U32 max_size = 4096; +        bool success = LLSDSerialize::deserialize(entry_llsd, in, max_size); +        // check bool(in) this time since eof is not a failure condition here +        if(!success || !in) { +            LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << LL_ENDL; +            return; +        } + +        LLGLTFOverrideCacheEntry entry; +        entry.fromLLSD(entry_llsd); +        U32 local_id = entry_llsd["local_id"].asInteger(); +        cache_extras_entry_map[local_id] = entry; +    } + +    LL_DEBUGS("GLTF") << "Completed reading extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL;  }  void LLVOCache::purgeEntries(U32 size) @@ -1520,6 +1608,7 @@ void LLVOCache::purgeEntries(U32 size)  		mHeaderEntryQueue.erase(iter) ;  		removeFromCache(entry) ;  		delete entry; +        // TODO also delete extras  	}  	mNumEntries = mHandleEntryMap.size() ;  } @@ -1649,4 +1738,59 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:  void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled)  { +    if(!mEnabled) +    { +        LL_WARNS() << "Not writing extras cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; +        return; +    } +    llassert_always(mInitialized); + +    if(mReadOnly) +    { +        LL_WARNS() << "Not writing extras cache for handle " << handle << "): Cache is currently in read-only mode." << LL_ENDL; +        return; +    } + +    std::string filename(getObjectCacheExtrasFilename(handle)); +    llofstream out(filename, std::ios::out | std::ios::binary); +    if(!out.good()) +    { +        LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; +        return; +        // TODO - clean up broken cache file +    } + +    out << id << '\n'; +    if(!out.good()) +    { +        LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; +        return; +        // TODO - clean up broken cache file +    } + +    U32 num_entries = cache_extras_entry_map.size(); +    out << num_entries << '\n'; +    if(!out.good()) +    { +        LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; +        return; +        // TODO - clean up broken cache file +    } + +    for (auto const & entry : cache_extras_entry_map) +    { +        S32 local_id = entry.first; +        LLSD entry_llsd = entry.second.toLLSD(); +        entry_llsd["local_id"] = local_id; +        LLSDSerialize::serialize(entry_llsd, out, LLSDSerialize::LLSD_XML); +        out << '\n'; +        if(!out.good()) +        { +            LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; +            return; +            // TODO - clean up broken cache file +        } +    } + +    LL_DEBUGS("GLTF") << "Completed writing extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL;  } diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index f41e9301ca..dcc8d37c5c 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -43,7 +43,7 @@ class LLGLTFOverrideCacheEntry  {  public:      bool fromLLSD(const LLSD& data); -    LLSD toLLSD(); +    LLSD toLLSD() const;      LLUUID mObjectId;      std::map<S32, std::string> mSides; //json per side @@ -301,6 +301,7 @@ private:  	void setDirNames(ELLPath location);	  	// determine the cache filename for the region from the region handle	  	void getObjectCacheFilename(U64 handle, std::string& filename); +    std::string getObjectCacheExtrasFilename(U64 handle);  	void removeFromCache(HeaderEntryInfo* entry);  	void readCacheHeader();  	void writeCacheHeader(); diff --git a/indra/newview/tests/lldir_stub.cpp b/indra/newview/tests/lldir_stub.cpp index 2bc6772d86..911e9334dd 100644 --- a/indra/newview/tests/lldir_stub.cpp +++ b/indra/newview/tests/lldir_stub.cpp @@ -30,25 +30,29 @@ LLDir::LLDir() {}  LLDir::~LLDir() {}  BOOL LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) { return true; }  void LLDir::setChatLogsDir(const std::string &path) {} -void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last) {} -void LLDir::setLindenUserDir(const std::string &first, const std::string &last) {} +void LLDir::setPerAccountChatLogsDir(const std::string &) {} +void LLDir::updatePerAccountChatLogsDir() {} +void LLDir::setLindenUserDir(const std::string &) {}  void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) {}  bool LLDir::setCacheDir(const std::string &path) { return true; } -void LLDir::dumpCurrentDirectories() {} +void LLDir::dumpCurrentDirectories(LLError::ELevel) {} +std::string LLDir::getSkinFolder() const { return ""; } +std::string LLDir::getLanguage() const { return ""; } +  class LLDir_stub : public LLDir  {  public: -	LLDir_stub() {} -	~LLDir_stub() {} +    LLDir_stub() = default; +    ~LLDir_stub() = default; + +	void initAppDirs(const std::string &app_name, const std::string &) override {} -	/*virtual*/ void initAppDirs(const std::string &app_name) {} +	std::string getCurPath() override { return "CUR_PATH_FROM_LLDIR"; } +    bool fileExists(const std::string &filename) const override { return false; } -	/*virtual*/ std::string getCurPath() { return "CUR_PATH_FROM_LLDIR"; } -	/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask) { return 42; } -	/*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) { fname = fname + "_NEXT"; return false; } -	/*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) { fname = "RANDOM_FILE"; } -	/*virtual*/ bool fileExists(const std::string &filename) const { return false; } +    std::string getLLPluginLauncher()  override { return ""; } +    std::string getLLPluginFilename(std::string base_name) override { return ""; }  };  LLDir_stub gDirUtil; @@ -60,3 +64,7 @@ std::string LLDir::getExpandedFilename(ELLPath loc, const std::string& subdir, c  	return subdir + " --- " + filename + " --- expanded!";  } +std::string LLDir::getExpandedFilename(ELLPath location, const std::string &filename) const +{ +    return filename + " --- expanded!"; +} diff --git a/indra/newview/tests/llvieweroctree_stub.cpp b/indra/newview/tests/llvieweroctree_stub.cpp new file mode 100644 index 0000000000..ab180c49a3 --- /dev/null +++ b/indra/newview/tests/llvieweroctree_stub.cpp @@ -0,0 +1,86 @@ +/**  + * @file llvieweroctree_stub.cpp + * @brief  stub implementations to allow unit testing + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad) { return 0; } + +void LLViewerOctreeCull::traverse(const LLOctreeNode<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry> >* node) { } +void LLViewerOctreeCull::visit(const LLOctreeNode<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry> >* node) { } +void LLViewerOctreeCull::preprocess(LLViewerOctreeGroup* group) {} +bool LLViewerOctreeCull::earlyFail(LLViewerOctreeGroup* group) { return false; } +bool LLViewerOctreeCull::checkProjectionArea(const LLVector4a& center, const LLVector4a& size, const LLVector3& shift, F32 pixel_threshold, F32 near_radius) { return false; } +bool LLViewerOctreeCull::checkObjects(const OctreeNode* branch, const LLViewerOctreeGroup* group) { return false; } +void LLViewerOctreeCull::processGroup(LLViewerOctreeGroup* group) {} + + +bool LLViewerOctreeGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut) { return false; } +void LLViewerOctreeGroup::unbound() {} +void LLViewerOctreeGroup::rebound() {} +void LLViewerOctreeGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* obj) {} +void LLViewerOctreeGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* obj) {} +void LLViewerOctreeGroup::handleDestruction(const TreeNode* node) {} +void LLViewerOctreeGroup::handleStateChange(const TreeNode* node) {} +void LLViewerOctreeGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) {} +void LLViewerOctreeGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child) {} + +LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part) : +    LLViewerOctreeGroup(node), +    mSpatialPartition(part) +{ +} +LLOcclusionCullingGroup::~LLOcclusionCullingGroup() = default; +void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* shift) {} +void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode) {} +void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode) {} +void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode *parent, OctreeNode *child) {} +BOOL LLOcclusionCullingGroup::isRecentlyVisible() const { return FALSE; } +BOOL LLOcclusionCullingGroup::isAnyRecentlyVisible() const { return FALSE; } + + +LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node) : mOctreeNode(node) {} +LLViewerOctreeGroup::~LLViewerOctreeGroup() = default; + +LLViewerOctreeEntryData::LLViewerOctreeEntryData(LLViewerOctreeEntry::eEntryDataType_t) {} +LLViewerOctreeEntryData::~LLViewerOctreeEntryData() = default; +bool LLViewerOctreeEntryData::isVisible() const { return false; } +bool LLViewerOctreeEntryData::isRecentlyVisible() const { return false; } +void LLViewerOctreeEntryData::setVisible() const {} +void LLViewerOctreeEntryData::resetVisible() const {} +const LLVector4a& LLViewerOctreeEntryData::getPositionGroup() const { return LLVector4a::getZero(); } +const LLVector4a* LLViewerOctreeEntryData::getSpatialExtents() const { return nullptr; } +LLViewerOctreeGroup* LLViewerOctreeEntryData::getGroup() const { return nullptr; } +void LLViewerOctreeEntryData::setSpatialExtents(const LLVector4a& min, const LLVector4a& max) {} +void LLViewerOctreeEntryData::setPositionGroup(const LLVector4a& pos) {} +void LLViewerOctreeEntryData::setGroup(LLViewerOctreeGroup* group) {} +void LLViewerOctreeEntryData::setOctreeEntry(LLViewerOctreeEntry* entry) {} +U32 LLViewerOctreeEntryData::sCurVisible{}; + +LLViewerOctreePartition::LLViewerOctreePartition() = default; +LLViewerOctreePartition::~LLViewerOctreePartition() = default; +void LLViewerOctreePartition::cleanup() {} + +BOOL LLViewerOctreeGroup::isRecentlyVisible() const { return FALSE; } + + diff --git a/indra/newview/tests/llvocache_test.cpp b/indra/newview/tests/llvocache_test.cpp new file mode 100644 index 0000000000..ea6abe254e --- /dev/null +++ b/indra/newview/tests/llvocache_test.cpp @@ -0,0 +1,146 @@ +/** + * @file llvocache_.cpp + * @author Brad + * @date 2023-03-01 + * @brief Test Viewer Object Cache functionality + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#include "../llviewerprecompiledheaders.h" +#include "../test/lltut.h" + +#include "llvocache.h" + +#include "lldir.h" +#include "llhudobject.h" +#include "llregionhandle.h" +#include "llsdutil.h" +#include "llsdserialize.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" + +#include "lldir_stub.cpp" +#include "llvieweroctree_stub.cpp" + +namespace +{ + +} + + +//---------------------------------------------------------------------------- +// Mock objects for the dependencies of the code we're testing +S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion) { return 0; } + +LLViewerObjectList::LLViewerObjectList() = default; +LLViewerObjectList::~LLViewerObjectList() = default; +LLDebugBeacon::~LLDebugBeacon() = default; +LLViewerObjectList gObjectList{}; +LLViewerCamera::eCameraID LLViewerCamera::sCurCameraID{}; +void LLViewerObject::unpackUUID(LLDataPackerBinaryBuffer *dp, LLUUID &value, std::string name) {} + +bool LLViewerRegion::addVisibleGroup(LLViewerOctreeGroup*) { return false; } +U32 LLViewerRegion::getNumOfVisibleGroups() const { return 0; } +LLVector3 LLViewerRegion::getOriginAgent() const { return LLVector3::zero; } +S32 LLViewerRegion::sLastCameraUpdated{}; + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ +    // Test wrapper declaration +    struct vocacheTest +    { +        vocacheTest() = default; +        ~vocacheTest() = default; + +        static const std::string override_llsd_text[]; +    }; + +    const std::string vocacheTest::override_llsd_text[]{ +        // sample override contents captured from traffic +        R"(<? llsd/notation ?> +        {'gltf_json':['{"asset":{"version":"2.0"},"images":[{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"}],"materials":[{"emissiveTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":3},"normalTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":1},"occlusionTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":4},"pbrMetallicRoughness":{"baseColorTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":0},"metallicRoughnessTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":2}}}],"textures":[{"source":0},{"source":1},{"source":2},{"source":3},{"source":4}]}\n','{"asset":{"version":"2.0"},"images":[{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"}],"materials":[{"emissiveTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":3},"normalTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":1},"occlusionTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":4},"pbrMetallicRoughness":{"baseColorTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":0},"metallicRoughnessTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":2}}}],"textures":[{"source":0},{"source":1},{"source":2},{"source":3},{"source":4}]}\n','{"asset":{"version":"2.0"},"images":[{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"}],"materials":[{"emissiveTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":3},"normalTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":1},"occlusionTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":4},"pbrMetallicRoughness":{"baseColorTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":0},"metallicRoughnessTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":2}}}],"textures":[{"source":0},{"source":1},{"source":2},{"source":3},{"source":4}]}\n','{"asset":{"version":"2.0"},"images":[{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"}],"materials":[{"emissiveTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":3},"normalTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":1},"occlusionTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":4},"pbrMetallicRoughness":{"baseColorTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":0},"metallicRoughnessTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":2}}}],"textures":[{"source":0},{"source":1},{"source":2},{"source":3},{"source":4}]}\n','{"asset":{"version":"2.0"},"images":[{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"}],"materials":[{"emissiveTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":3},"normalTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":1},"occlusionTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":4},"pbrMetallicRoughness":{"baseColorTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":0},"metallicRoughnessTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":2}}}],"textures":[{"source":0},{"source":1},{"source":2},{"source":3},{"source":4}]}\n','{"asset":{"version":"2.0"},"images":[{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"}],"materials":[{"emissiveTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":3},"normalTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":1},"occlusionTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":4},"pbrMetallicRoughness":{"baseColorTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":0},"metallicRoughnessTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":2}}}],"textures":[{"source":0},{"source":1},{"source":2},{"source":3},{"source":4}]}\n','{"asset":{"version":"2.0"},"images":[{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"},{"uri":"00000000-0000-0000-0000-000000000000"}],"materials":[{"emissiveTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":3},"normalTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":1},"occlusionTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":4},"pbrMetallicRoughness":{"baseColorTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":0},"metallicRoughnessTexture":{"extensions":{"KHR_texture_transform":{"offset":[0.0,0.0],"rotation":0.0,"scale":[2.0,2.0]}},"index":2}}}],"textures":[{"source":0},{"source":1},{"source":2},{"source":3},{"source":4}]}\n'],'object_id':u8b357110-4845-1d40-1cf0-cc4a2c22a4f1,'sides':[i0,i1,i2,i3,i4,i5,i6]})" +    }; + +    // Tut templating thingamagic: test group, object and test instance +    struct vocacheTestFactory : public test_group<vocacheTest> +    { +        vocacheTestFactory() +            : test_group<vocacheTest>("LLVOCache") +        { +            ll_init_apr(); + +            const bool READ_ONLY = false; +            const U32 INDRA_OBJECT_CACHE_VERSION = 15; // see LLAppViewer::getObjectCacheVersion() +            const U32 CACHE_NUMBER_OF_REGIONS = 128;   // see setting CacheNumberOfRegionsForObjects + +            LLVOCache &instance = LLVOCache::initParamSingleton(READ_ONLY); +            instance.initCache(LL_PATH_CACHE, CACHE_NUMBER_OF_REGIONS, INDRA_OBJECT_CACHE_VERSION); +        } + +        ~vocacheTestFactory() +        { +            LLVOCache::deleteSingleton(); +            ll_cleanup_apr(); +        } + +    }; + +    typedef vocacheTestFactory::object vocacheTestObject; +    tut::vocacheTestFactory tut_test; + +    // --------------------------------------------------------------------------------------- +    // Test functions +    // --------------------------------------------------------------------------------------- + +    template<> template<> +    void vocacheTestObject::test<1>() +    { +        LLGLTFOverrideCacheEntry entry{}; +        LLSD entry_llsd; + +        std::istringstream in_llsd(override_llsd_text[0]); +        bool success = LLSDSerialize::deserialize(entry_llsd, in_llsd, override_llsd_text[0].length()); + +        ensure("llsd deserialize succeeds", success); + +        entry.fromLLSD(entry_llsd); +        ensure_equals("entry object_id match", entry.mObjectId, LLUUID("8b357110-4845-1d40-1cf0-cc4a2c22a4f1")); +        ensure_equals("sides count", entry.mSides.size(), 7); + +        //std::cout << other << std::endl; +        ensure_equals("toLLSD() match", entry.toLLSD(), entry_llsd); +    } + +    template<> template<> +    void vocacheTestObject::test<2>() +    { +        LLVOCacheEntry::vocache_gltf_overrides_map_t extras; + +        U64 region_handle = to_region_handle(140, 81); +        LLUUID region_id = LLUUID::generateNewID(); + +        LLVOCache::instance().readGenericExtrasFromCache(region_handle, region_id, extras); +    } +} | 
