// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace anki { static NumericCVar g_transferScratchMemorySizeCVar(CVarSubsystem::kResource, "TransferScratchMemorySize", 256_MB, 1_MB, 4_GB, "Memory that is used fot texture and buffer uploads"); ResourceManager::ResourceManager() { } ResourceManager::~ResourceManager() { ANKI_RESOURCE_LOGI("Destroying resource manager"); deleteInstance(ResourceMemoryPool::getSingleton(), m_asyncLoader); deleteInstance(ResourceMemoryPool::getSingleton(), m_shaderProgramSystem); deleteInstance(ResourceMemoryPool::getSingleton(), m_transferGpuAlloc); deleteInstance(ResourceMemoryPool::getSingleton(), m_fs); ResourceMemoryPool::freeSingleton(); } Error ResourceManager::init(AllocAlignedCallback allocCallback, void* allocCallbackData) { ANKI_RESOURCE_LOGI("Initializing resource manager"); ResourceMemoryPool::allocateSingleton(allocCallback, allocCallbackData); m_fs = newInstance(ResourceMemoryPool::getSingleton()); ANKI_CHECK(m_fs->init()); // Init the thread m_asyncLoader = newInstance(ResourceMemoryPool::getSingleton()); m_transferGpuAlloc = newInstance(ResourceMemoryPool::getSingleton()); ANKI_CHECK(m_transferGpuAlloc->init(g_transferScratchMemorySizeCVar.get())); // Init the programs m_shaderProgramSystem = newInstance(ResourceMemoryPool::getSingleton()); ANKI_CHECK(m_shaderProgramSystem->init()); return Error::kNone; } U64 ResourceManager::getAsyncTaskCompletedCount() const { return m_asyncLoader->getCompletedTaskCount(); } template Error ResourceManager::loadResource(const CString& filename, ResourcePtr& out, Bool async) { ANKI_ASSERT(!out.isCreated() && "Already loaded"); Error err = Error::kNone; ++m_loadRequestCount; T* const other = findLoadedResource(filename); if(other) { // Found out.reset(other); } else { // Allocate ptr T* ptr = newInstance(ResourceMemoryPool::getSingleton()); ANKI_ASSERT(ptr->getRefcount() == 0); // Increment the refcount in that case where async jobs increment it and decrement it in the scope of a load() ptr->retain(); err = ptr->load(filename, async); if(err) { ANKI_RESOURCE_LOGE("Failed to load resource: %s", &filename[0]); deleteInstance(ResourceMemoryPool::getSingleton(), ptr); return err; } ptr->setFilename(filename); ptr->setUuid(++m_uuid); // Register resource registerResource(ptr); out.reset(ptr); // Decrement because of the increment happened a few lines above ptr->release(); } return err; } // Instansiate the ResourceManager::loadResource() #define ANKI_INSTANTIATE_RESOURCE(rsrc_, ptr_) \ template Error ResourceManager::loadResource(const CString& filename, ResourcePtr& out, Bool async); #define ANKI_INSTANSIATE_RESOURCE_DELIMITER() #include #undef ANKI_INSTANTIATE_RESOURCE #undef ANKI_INSTANSIATE_RESOURCE_DELIMITER } // end namespace anki