mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Core / VideoCommon: Remove original custom asset loader
This commit is contained in:
@ -1,108 +0,0 @@
|
||||
// Copyright 2023 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "VideoCommon/Assets/CustomAssetLoader.h"
|
||||
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "VideoCommon/Assets/CustomAssetLibrary.h"
|
||||
|
||||
namespace VideoCommon
|
||||
{
|
||||
void CustomAssetLoader::Init()
|
||||
{
|
||||
m_asset_monitor_thread_shutdown.Clear();
|
||||
|
||||
const size_t sys_mem = Common::MemPhysical();
|
||||
const size_t recommended_min_mem = 2 * size_t(1024 * 1024 * 1024);
|
||||
// keep 2GB memory for system stability if system RAM is 4GB+ - use half of memory in other cases
|
||||
m_max_memory_available =
|
||||
(sys_mem / 2 < recommended_min_mem) ? (sys_mem / 2) : (sys_mem - recommended_min_mem);
|
||||
|
||||
m_asset_monitor_thread = std::thread([this]() {
|
||||
Common::SetCurrentThreadName("Asset monitor");
|
||||
while (true)
|
||||
{
|
||||
if (m_asset_monitor_thread_shutdown.IsSet())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(TIME_BETWEEN_ASSET_MONITOR_CHECKS);
|
||||
|
||||
std::lock_guard lk(m_asset_load_lock);
|
||||
for (auto& [asset_id, asset_to_monitor] : m_assets_to_monitor)
|
||||
{
|
||||
if (auto ptr = asset_to_monitor.lock())
|
||||
{
|
||||
const auto write_time = ptr->GetLastWriteTime();
|
||||
if (write_time > ptr->GetLastLoadedTime())
|
||||
{
|
||||
(void)ptr->Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
m_asset_load_thread.Reset("Custom Asset Loader", [this](std::weak_ptr<CustomAsset> asset) {
|
||||
if (auto ptr = asset.lock())
|
||||
{
|
||||
if (m_memory_exceeded)
|
||||
return;
|
||||
|
||||
if (ptr->Load())
|
||||
{
|
||||
std::lock_guard lk(m_asset_load_lock);
|
||||
const std::size_t asset_memory_size = ptr->GetByteSizeInMemory();
|
||||
m_total_bytes_loaded += asset_memory_size;
|
||||
m_assets_to_monitor.try_emplace(ptr->GetAssetId(), ptr);
|
||||
if (m_total_bytes_loaded > m_max_memory_available)
|
||||
{
|
||||
ERROR_LOG_FMT(VIDEO,
|
||||
"Asset memory exceeded with asset '{}', future assets won't load until "
|
||||
"memory is available.",
|
||||
ptr->GetAssetId());
|
||||
m_memory_exceeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CustomAssetLoader::Shutdown()
|
||||
{
|
||||
m_asset_load_thread.StopAndCancel();
|
||||
|
||||
m_asset_monitor_thread_shutdown.Set();
|
||||
m_asset_monitor_thread.join();
|
||||
m_assets_to_monitor.clear();
|
||||
m_total_bytes_loaded = 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<GameTextureAsset>
|
||||
CustomAssetLoader::LoadGameTexture(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library)
|
||||
{
|
||||
return LoadOrCreateAsset<GameTextureAsset>(asset_id, m_game_textures, std::move(library));
|
||||
}
|
||||
|
||||
std::shared_ptr<PixelShaderAsset>
|
||||
CustomAssetLoader::LoadPixelShader(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library)
|
||||
{
|
||||
return LoadOrCreateAsset<PixelShaderAsset>(asset_id, m_pixel_shaders, std::move(library));
|
||||
}
|
||||
|
||||
std::shared_ptr<MaterialAsset>
|
||||
CustomAssetLoader::LoadMaterial(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library)
|
||||
{
|
||||
return LoadOrCreateAsset<MaterialAsset>(asset_id, m_materials, std::move(library));
|
||||
}
|
||||
|
||||
std::shared_ptr<MeshAsset> CustomAssetLoader::LoadMesh(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library)
|
||||
{
|
||||
return LoadOrCreateAsset<MeshAsset>(asset_id, m_meshes, std::move(library));
|
||||
}
|
||||
} // namespace VideoCommon
|
@ -1,108 +0,0 @@
|
||||
// Copyright 2023 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "Common/Flag.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/WorkQueueThread.h"
|
||||
#include "VideoCommon/Assets/CustomAsset.h"
|
||||
#include "VideoCommon/Assets/MaterialAsset.h"
|
||||
#include "VideoCommon/Assets/MeshAsset.h"
|
||||
#include "VideoCommon/Assets/ShaderAsset.h"
|
||||
#include "VideoCommon/Assets/TextureAsset.h"
|
||||
|
||||
namespace VideoCommon
|
||||
{
|
||||
// This class is responsible for loading data asynchronously when requested
|
||||
// and watches that data asynchronously reloading it if it changes
|
||||
class CustomAssetLoader
|
||||
{
|
||||
public:
|
||||
CustomAssetLoader() = default;
|
||||
~CustomAssetLoader() = default;
|
||||
CustomAssetLoader(const CustomAssetLoader&) = delete;
|
||||
CustomAssetLoader(CustomAssetLoader&&) = delete;
|
||||
CustomAssetLoader& operator=(const CustomAssetLoader&) = delete;
|
||||
CustomAssetLoader& operator=(CustomAssetLoader&&) = delete;
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
// The following Load* functions will load or create an asset associated
|
||||
// with the given asset id
|
||||
// Loads happen asynchronously where the data will be set now or in the future
|
||||
// Callees are expected to query the underlying data with 'GetData()'
|
||||
// from the 'CustomLoadableAsset' class to determine if the data is ready for use
|
||||
std::shared_ptr<GameTextureAsset> LoadGameTexture(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library);
|
||||
|
||||
std::shared_ptr<PixelShaderAsset> LoadPixelShader(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library);
|
||||
|
||||
std::shared_ptr<MaterialAsset> LoadMaterial(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library);
|
||||
|
||||
std::shared_ptr<MeshAsset> LoadMesh(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::shared_ptr<CustomAssetLibrary> library);
|
||||
|
||||
private:
|
||||
// TODO C++20: use a 'derived_from' concept against 'CustomAsset' when available
|
||||
template <typename AssetType>
|
||||
std::shared_ptr<AssetType>
|
||||
LoadOrCreateAsset(const CustomAssetLibrary::AssetID& asset_id,
|
||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<AssetType>>& asset_map,
|
||||
std::shared_ptr<CustomAssetLibrary> library)
|
||||
{
|
||||
auto [it, inserted] = asset_map.try_emplace(asset_id);
|
||||
if (!inserted)
|
||||
{
|
||||
auto shared = it->second.lock();
|
||||
if (shared)
|
||||
return shared;
|
||||
}
|
||||
std::shared_ptr<AssetType> ptr(new AssetType(std::move(library), asset_id), [&](AssetType* a) {
|
||||
{
|
||||
std::lock_guard lk(m_asset_load_lock);
|
||||
m_total_bytes_loaded -= a->GetByteSizeInMemory();
|
||||
m_assets_to_monitor.erase(a->GetAssetId());
|
||||
if (m_max_memory_available >= m_total_bytes_loaded && m_memory_exceeded)
|
||||
{
|
||||
INFO_LOG_FMT(VIDEO, "Asset memory went below limit, new assets can begin loading.");
|
||||
m_memory_exceeded = false;
|
||||
}
|
||||
}
|
||||
delete a;
|
||||
});
|
||||
it->second = ptr;
|
||||
m_asset_load_thread.Push(it->second);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static constexpr auto TIME_BETWEEN_ASSET_MONITOR_CHECKS = std::chrono::milliseconds{500};
|
||||
|
||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<GameTextureAsset>> m_game_textures;
|
||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<PixelShaderAsset>> m_pixel_shaders;
|
||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<MaterialAsset>> m_materials;
|
||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<MeshAsset>> m_meshes;
|
||||
std::thread m_asset_monitor_thread;
|
||||
Common::Flag m_asset_monitor_thread_shutdown;
|
||||
|
||||
std::size_t m_total_bytes_loaded = 0;
|
||||
std::size_t m_max_memory_available = 0;
|
||||
std::atomic_bool m_memory_exceeded = false;
|
||||
|
||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<CustomAsset>> m_assets_to_monitor;
|
||||
|
||||
// Use a recursive mutex to handle the scenario where an asset goes out of scope while
|
||||
// iterating over the assets to monitor which calls the lock above in 'LoadOrCreateAsset'
|
||||
std::recursive_mutex m_asset_load_lock;
|
||||
Common::WorkQueueThread<std::weak_ptr<CustomAsset>> m_asset_load_thread;
|
||||
};
|
||||
} // namespace VideoCommon
|
Reference in New Issue
Block a user