summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2023-06-02 23:59:27 +0200
committerGitHub <noreply@github.com>2023-06-02 23:59:27 +0200
commit4ee27404eeeb30e8f6a8a20be92d21cb6c96e8e4 (patch)
tree5101b162f2f0c89746fffbc819f4750d2e53f40d /Source
parent6028c056444cb5d89d72377b1547adef084211e6 (diff)
parent07307edd49497da157dcb29e5b32bb884b4f4b89 (diff)
Merge pull request #11876 from iwubcode/directfilesystem_asset_library
VideoCommon: add an asset library that loads directly from the filesystem
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/DolphinLib.props2
-rw-r--r--Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp145
-rw-r--r--Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.h37
-rw-r--r--Source/Core/VideoCommon/CMakeLists.txt2
4 files changed, 186 insertions, 0 deletions
diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props
index bc50241e60..5ae7b6fd67 100644
--- a/Source/Core/DolphinLib.props
+++ b/Source/Core/DolphinLib.props
@@ -634,6 +634,7 @@
<ClInclude Include="VideoCommon\Assets\CustomAsset.h" />
<ClInclude Include="VideoCommon\Assets\CustomAssetLibrary.h" />
<ClInclude Include="VideoCommon\Assets\CustomTextureData.h" />
+ <ClInclude Include="VideoCommon\Assets\DirectFilesystemAssetLibrary.h" />
<ClInclude Include="VideoCommon\AsyncRequests.h" />
<ClInclude Include="VideoCommon\AsyncShaderCompiler.h" />
<ClInclude Include="VideoCommon\BoundingBox.h" />
@@ -1246,6 +1247,7 @@
<ClCompile Include="VideoCommon\Assets\CustomAsset.cpp" />
<ClCompile Include="VideoCommon\Assets\CustomAssetLibrary.cpp" />
<ClCompile Include="VideoCommon\Assets\CustomTextureData.cpp" />
+ <ClCompile Include="VideoCommon\Assets\DirectFilesystemAssetLibrary.cpp" />
<ClCompile Include="VideoCommon\AsyncRequests.cpp" />
<ClCompile Include="VideoCommon\AsyncShaderCompiler.cpp" />
<ClCompile Include="VideoCommon\BoundingBox.cpp" />
diff --git a/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp b/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp
new file mode 100644
index 0000000000..912def9e6b
--- /dev/null
+++ b/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp
@@ -0,0 +1,145 @@
+// Copyright 2023 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "VideoCommon/Assets/DirectFilesystemAssetLibrary.h"
+
+#include <algorithm>
+
+#include "Common/FileUtil.h"
+#include "Common/Logging/Log.h"
+#include "Common/StringUtil.h"
+#include "VideoCommon/Assets/CustomTextureData.h"
+
+namespace VideoCommon
+{
+namespace
+{
+std::size_t GetAssetSize(const CustomTextureData& data)
+{
+ std::size_t total = 0;
+ for (const auto& level : data.m_levels)
+ {
+ total += level.data.size();
+ }
+ return total;
+}
+} // namespace
+CustomAssetLibrary::TimeType
+DirectFilesystemAssetLibrary::GetLastAssetWriteTime(const AssetID& asset_id) const
+{
+ if (auto iter = m_assetid_to_asset_map_path.find(asset_id);
+ iter != m_assetid_to_asset_map_path.end())
+ {
+ const auto& asset_map_path = iter->second;
+ CustomAssetLibrary::TimeType max_entry;
+ for (const auto& [key, value] : asset_map_path)
+ {
+ const auto tp = std::filesystem::last_write_time(value);
+ if (tp > max_entry)
+ max_entry = tp;
+ }
+ return max_entry;
+ }
+
+ return {};
+}
+
+CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadTexture(const AssetID& asset_id,
+ CustomTextureData* data)
+{
+ if (auto iter = m_assetid_to_asset_map_path.find(asset_id);
+ iter != m_assetid_to_asset_map_path.end())
+ {
+ const auto& asset_map_path = iter->second;
+
+ // Raw texture is expected to have one asset mapped
+ if (asset_map_path.empty() || asset_map_path.size() > 1)
+ return {};
+ const auto& asset_path = asset_map_path.begin()->second;
+
+ const auto last_loaded_time = std::filesystem::last_write_time(asset_path);
+ auto ext = asset_path.extension().string();
+ Common::ToLower(&ext);
+ if (ext == ".dds")
+ {
+ LoadDDSTexture(data, asset_path.string());
+ if (data->m_levels.empty()) [[unlikely]]
+ return {};
+ if (!LoadMips(asset_path, data))
+ return {};
+
+ return LoadInfo{GetAssetSize(*data), last_loaded_time};
+ }
+ else if (ext == ".png")
+ {
+ LoadPNGTexture(data, asset_path.string());
+ if (data->m_levels.empty()) [[unlikely]]
+ return {};
+ if (!LoadMips(asset_path, data))
+ return {};
+
+ return LoadInfo{GetAssetSize(*data), last_loaded_time};
+ }
+ }
+
+ return {};
+}
+
+void DirectFilesystemAssetLibrary::SetAssetIDMapData(
+ const AssetID& asset_id, std::map<std::string, std::filesystem::path> asset_path_map)
+{
+ m_assetid_to_asset_map_path[asset_id] = std::move(asset_path_map);
+}
+
+bool DirectFilesystemAssetLibrary::LoadMips(const std::filesystem::path& asset_path,
+ CustomTextureData* data)
+{
+ if (!data) [[unlikely]]
+ return false;
+
+ std::string path;
+ std::string filename;
+ std::string extension;
+ SplitPath(asset_path.string(), &path, &filename, &extension);
+
+ std::string extension_lower = extension;
+ Common::ToLower(&extension_lower);
+
+ // Load additional mip levels
+ for (u32 mip_level = static_cast<u32>(data->m_levels.size());; mip_level++)
+ {
+ const auto mip_level_filename = filename + fmt::format("_mip{}", mip_level);
+
+ const auto full_path = path + mip_level_filename + extension;
+ if (!File::Exists(full_path))
+ return true;
+
+ VideoCommon::CustomTextureData::Level level;
+ if (extension_lower == ".dds")
+ {
+ if (!LoadDDSTexture(&level, full_path, mip_level))
+ {
+ ERROR_LOG_FMT(VIDEO, "Custom mipmap '{}' failed to load", mip_level_filename);
+ return false;
+ }
+ }
+ else if (extension_lower == ".png")
+ {
+ if (!LoadPNGTexture(&level, full_path))
+ {
+ ERROR_LOG_FMT(VIDEO, "Custom mipmap '{}' failed to load", mip_level_filename);
+ return false;
+ }
+ }
+ else
+ {
+ ERROR_LOG_FMT(VIDEO, "Custom mipmap '{}' has unsupported extension", mip_level_filename);
+ return false;
+ }
+
+ data->m_levels.push_back(std::move(level));
+ }
+
+ return true;
+}
+} // namespace VideoCommon
diff --git a/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.h b/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.h
new file mode 100644
index 0000000000..d04981dac3
--- /dev/null
+++ b/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.h
@@ -0,0 +1,37 @@
+// Copyright 2023 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+#include <chrono>
+#include <filesystem>
+#include <map>
+#include <string>
+
+#include "VideoCommon/Assets/CustomAssetLibrary.h"
+
+namespace VideoCommon
+{
+class CustomTextureData;
+
+// This class implements 'CustomAssetLibrary' and loads any assets
+// directly from the filesystem
+class DirectFilesystemAssetLibrary final : public CustomAssetLibrary
+{
+public:
+ LoadInfo LoadTexture(const AssetID& asset_id, CustomTextureData* data) override;
+
+ // Gets the latest time from amongst all the files in the asset map
+ TimeType GetLastAssetWriteTime(const AssetID& asset_id) const override;
+
+ // Assigns the asset id to a map of files, how this map is read is dependent on the data
+ // For instance, a raw texture would expect the map to have a single entry and load that
+ // file as the asset. But a model file data might have its data spread across multiple files
+ void SetAssetIDMapData(const AssetID& asset_id,
+ std::map<std::string, std::filesystem::path> asset_path_map);
+
+private:
+ // Loads additional mip levels into the texture structure until _mip<N> texture is not found
+ bool LoadMips(const std::filesystem::path& asset_path, CustomTextureData* data);
+ std::map<AssetID, std::map<std::string, std::filesystem::path>> m_assetid_to_asset_map_path;
+};
+} // namespace VideoCommon
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index 7ad8f45681..fa2811b410 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -14,6 +14,8 @@ add_library(videocommon
Assets/CustomAssetLibrary.h
Assets/CustomTextureData.cpp
Assets/CustomTextureData.h
+ Assets/DirectFilesystemAssetLibrary.cpp
+ Assets/DirectFilesystemAssetLibrary.h
AsyncRequests.cpp
AsyncRequests.h
AsyncShaderCompiler.cpp