
글에 사용된 모든 그림과 내용은 직접 작성한 것입니다.
[유튜브 영상]
[깃허브 보러가기]
https://github.com/Chang-Jin-Lee/D3D11-AliceTutorial/tree/main/28_Scene_Shared3DModel_Animation
[풀리퀘 보러가기]
https://github.com/Chang-Jin-Lee/D3D11-AliceTutorial/pull/58
D3D11에서 리소스 매니저가 필요한 이유와 어떤 방법으로 구현할 수 있는지 정리하기 위함

| 2개 있을때 | 같은 모델이 여러 개 그려져도 VRAM이 증가하지 않는다 |
|---|---|
VRAM 1963.24 MB | VRAM 1963.24 MB |
![]() |
자원을 공유하고 있는 모델
|
struct AssetKey
{
std::wstring PathW;
EAssetKind Kind;
bool operator==(const AssetKey& other) const
{
return Kind == other.Kind && PathW == other.PathW;
}
};
class AssetManager : public Singleton<AssetManager>
{
public:
AssetManager() = default;
std::shared_ptr<FbxModel> GetFbxModel(ID3D11Device* device, const std::wstring& pathW);
private:
std::unordered_map<AssetKey, std::weak_ptr<FbxModel>, AssetKey::Hash> m_FbxCache;};
}
std::shared_ptr<FbxModel> AssetManager::GetFbxModel(ID3D11Device* device, const std::wstring& pathW)
{
if (!device || pathW.empty()) return nullptr;
// AssetKey로 캐시 조회
AssetKey key{ pathW, EAssetKind::FbxModel };
if (auto it = m_FbxCache.find(key); it != m_FbxCache.end())
{
if (auto sp = it->second.lock())
{
return sp; // 재사용
}
else
{
m_FbxCache.erase(it); // 만료된 weak_ptr 정리
}
}
// 새로 로드
auto model = std::make_shared<FbxModel>();
if (!model->Load(device, pathW))
{
return nullptr;
}
m_FbxCache[key] = model;
return model;
}
uint64_t AssetManager::ComputeFileHash(const std::wstring& pathW)
{
if (!std::filesystem::exists(pathW)) return 0;
auto fileSize = std::filesystem::file_size(pathW);
auto writeTime = std::filesystem::last_write_time(pathW);
std::uint64_t timeHash = static_cast<std::uint64_t>(writeTime.time_since_epoch().count());
uint64_t sizeHash = fileSize;
const size_t SAMPLE_SIZE = 4096;
std::ifstream file(pathW, std::ios::binary);
if (!file.is_open()) return 0;
uint8_t buffer[SAMPLE_SIZE * 2] = { 0 };
size_t readSize = 0;
if (fileSize > 0)
{
size_t toRead = (std::min)(SAMPLE_SIZE, static_cast<size_t>(fileSize));
file.read(reinterpret_cast<char*>(buffer), toRead);
readSize += static_cast<size_t>(file.gcount());
}
if (fileSize > SAMPLE_SIZE)
{
file.seekg(-static_cast<std::streamoff>((std::min)(SAMPLE_SIZE, static_cast<size_t>(fileSize))), std::ios::end);
file.read(reinterpret_cast<char*>(buffer + readSize), SAMPLE_SIZE);
readSize += static_cast<size_t>(file.gcount());
}
file.close();
uint64_t sampleHash = FNV1a64(buffer, readSize);
uint64_t finalHash = sizeHash;
finalHash ^= (timeHash << 1);
finalHash ^= (sampleHash << 2);
return finalHash;
}