diff --git a/apps/components_tests/CMakeLists.txt b/apps/components_tests/CMakeLists.txt index 7595681313..890998a32c 100644 --- a/apps/components_tests/CMakeLists.txt +++ b/apps/components_tests/CMakeLists.txt @@ -84,6 +84,7 @@ file(GLOB UNITTEST_SRC_FILES esmterrain/testgridsampling.cpp resource/testobjectcache.cpp + resource/testresourcesystem.cpp vfs/testpathutil.cpp diff --git a/apps/components_tests/resource/testresourcesystem.cpp b/apps/components_tests/resource/testresourcesystem.cpp new file mode 100644 index 0000000000..c863ba72e9 --- /dev/null +++ b/apps/components_tests/resource/testresourcesystem.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +#include +#include + +#include + +namespace +{ + using namespace testing; + + TEST(ResourceResourceSystem, scenemanager_getinstance_should_be_thread_safe) + { + const VFS::Manager vfsManager; + const ToUTF8::Utf8Encoder encoder(ToUTF8::WINDOWS_1252); + Resource::ResourceSystem resourceSystem(&vfsManager, 1.0, &encoder.getStatelessEncoder()); + Resource::SceneManager* sceneManager = resourceSystem.getSceneManager(); + + constexpr VFS::Path::NormalizedView noSuchPath("meshes/whatever.nif"); + std::vector threads; + + for (int i = 0; i < 50; ++i) + { + threads.emplace_back([=]() { sceneManager->getInstance(noSuchPath); }); + } + for (std::thread& thread : threads) + thread.join(); + } +} diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 84ba08c0b3..ffa6abe58e 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -446,15 +446,6 @@ namespace Resource Resource::NifFileManager* nifFileManager, Resource::BgsmFileManager* bgsmFileManager, double expiryDelay) : ResourceManager(vfs, expiryDelay) , mShaderManager(new Shader::ShaderManager) - , mForceShaders(false) - , mClampLighting(true) - , mAutoUseNormalMaps(false) - , mAutoUseSpecularMaps(false) - , mApplyLightingToEnvMaps(false) - , mLightingMethod(SceneUtil::LightingMethod::FFP) - , mConvertAlphaTestToAlphaToCoverage(false) - , mAdjustCoverageForAlphaTest(false) - , mSupportsNormalsRT(false) , mSharedStateManager(new SharedStateManager) , mImageManager(imageManager) , mNifFileManager(nifFileManager) @@ -462,8 +453,8 @@ namespace Resource , mMinFilter(osg::Texture::LINEAR_MIPMAP_LINEAR) , mMagFilter(osg::Texture::LINEAR) , mMaxAnisotropy(1) - , mUnRefImageDataAfterApply(false) , mParticleSystemMask(~0u) + , mLightingMethod(SceneUtil::LightingMethod::FFP) { } @@ -988,8 +979,7 @@ namespace Resource osg::ref_ptr SceneManager::cloneErrorMarker() { - if (!mErrorMarker) - mErrorMarker = loadErrorMarker(); + std::call_once(mErrorMarkerFlag, [this] { mErrorMarker = loadErrorMarker(); }); return static_cast(mErrorMarker->clone(osg::CopyOp::DEEP_COPY_ALL)); } diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index 370383975d..df37a6165a 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -237,42 +237,43 @@ namespace Resource osg::ref_ptr loadErrorMarker(); osg::ref_ptr cloneErrorMarker(); + mutable std::mutex mSharedStateMutex; + std::unique_ptr mShaderManager; - bool mForceShaders; - bool mClampLighting; - bool mAutoUseNormalMaps; std::string mNormalMapPattern; std::string mNormalHeightMapPattern; - bool mAutoUseSpecularMaps; std::string mSpecularMapPattern; - bool mApplyLightingToEnvMaps; - SceneUtil::LightingMethod mLightingMethod; - SceneUtil::LightManager::SupportedMethods mSupportedLightingMethods; - bool mConvertAlphaTestToAlphaToCoverage; - bool mAdjustCoverageForAlphaTest; - bool mSupportsNormalsRT; std::array, 2> mOpaqueDepthTex; - bool mWeatherParticleOcclusion = false; osg::ref_ptr mSharedStateManager; - mutable std::mutex mSharedStateMutex; Resource::ImageManager* mImageManager; Resource::NifFileManager* mNifFileManager; Resource::BgsmFileManager* mBgsmFileManager; + osg::ref_ptr mIncrementalCompileOperation; + mutable osg::ref_ptr mErrorMarker; + mutable std::once_flag mErrorMarkerFlag; osg::Texture::FilterMode mMinFilter; osg::Texture::FilterMode mMagFilter; int mMaxAnisotropy; - bool mUnRefImageDataAfterApply; - - osg::ref_ptr mIncrementalCompileOperation; unsigned int mParticleSystemMask; - mutable osg::ref_ptr mErrorMarker; + SceneUtil::LightingMethod mLightingMethod; + SceneUtil::LightManager::SupportedMethods mSupportedLightingMethods; + bool mForceShaders = false; + bool mClampLighting = true; + bool mAutoUseNormalMaps = false; + bool mAutoUseSpecularMaps = false; + bool mApplyLightingToEnvMaps = false; + bool mConvertAlphaTestToAlphaToCoverage = false; + bool mAdjustCoverageForAlphaTest = false; + bool mSupportsNormalsRT = false; + bool mWeatherParticleOcclusion = false; + bool mUnRefImageDataAfterApply = false; - SceneManager(const SceneManager&); - void operator=(const SceneManager&); + SceneManager(const SceneManager&) = delete; + void operator=(const SceneManager&) = delete; }; }