mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-16 12:58:33 +02:00
VideoCommon: make mesh asset data loadable by asset loader
This commit is contained in:
@ -11,6 +11,7 @@
|
|||||||
namespace VideoCommon
|
namespace VideoCommon
|
||||||
{
|
{
|
||||||
struct MaterialData;
|
struct MaterialData;
|
||||||
|
struct MeshData;
|
||||||
struct PixelShaderData;
|
struct PixelShaderData;
|
||||||
struct TextureData;
|
struct TextureData;
|
||||||
|
|
||||||
@ -48,5 +49,8 @@ public:
|
|||||||
|
|
||||||
// Loads a material
|
// Loads a material
|
||||||
virtual LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) = 0;
|
virtual LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) = 0;
|
||||||
|
|
||||||
|
// Loads a mesh
|
||||||
|
virtual LoadInfo LoadMesh(const AssetID& asset_id, MeshData* data) = 0;
|
||||||
};
|
};
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
@ -97,4 +97,10 @@ CustomAssetLoader::LoadMaterial(const CustomAssetLibrary::AssetID& asset_id,
|
|||||||
{
|
{
|
||||||
return LoadOrCreateAsset<MaterialAsset>(asset_id, m_materials, std::move(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
|
} // namespace VideoCommon
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "Common/WorkQueueThread.h"
|
#include "Common/WorkQueueThread.h"
|
||||||
#include "VideoCommon/Assets/CustomAsset.h"
|
#include "VideoCommon/Assets/CustomAsset.h"
|
||||||
#include "VideoCommon/Assets/MaterialAsset.h"
|
#include "VideoCommon/Assets/MaterialAsset.h"
|
||||||
|
#include "VideoCommon/Assets/MeshAsset.h"
|
||||||
#include "VideoCommon/Assets/ShaderAsset.h"
|
#include "VideoCommon/Assets/ShaderAsset.h"
|
||||||
#include "VideoCommon/Assets/TextureAsset.h"
|
#include "VideoCommon/Assets/TextureAsset.h"
|
||||||
|
|
||||||
@ -47,6 +48,9 @@ public:
|
|||||||
std::shared_ptr<MaterialAsset> LoadMaterial(const CustomAssetLibrary::AssetID& asset_id,
|
std::shared_ptr<MaterialAsset> LoadMaterial(const CustomAssetLibrary::AssetID& asset_id,
|
||||||
std::shared_ptr<CustomAssetLibrary> library);
|
std::shared_ptr<CustomAssetLibrary> library);
|
||||||
|
|
||||||
|
std::shared_ptr<MeshAsset> LoadMesh(const CustomAssetLibrary::AssetID& asset_id,
|
||||||
|
std::shared_ptr<CustomAssetLibrary> library);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO C++20: use a 'derived_from' concept against 'CustomAsset' when available
|
// TODO C++20: use a 'derived_from' concept against 'CustomAsset' when available
|
||||||
template <typename AssetType>
|
template <typename AssetType>
|
||||||
@ -80,6 +84,7 @@ private:
|
|||||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<GameTextureAsset>> m_game_textures;
|
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<PixelShaderAsset>> m_pixel_shaders;
|
||||||
std::map<CustomAssetLibrary::AssetID, std::weak_ptr<MaterialAsset>> m_materials;
|
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;
|
std::thread m_asset_monitor_thread;
|
||||||
Common::Flag m_asset_monitor_thread_shutdown;
|
Common::Flag m_asset_monitor_thread_shutdown;
|
||||||
|
|
||||||
|
@ -4,13 +4,16 @@
|
|||||||
#include "VideoCommon/Assets/DirectFilesystemAssetLibrary.h"
|
#include "VideoCommon/Assets/DirectFilesystemAssetLibrary.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <fmt/std.h>
|
#include <fmt/std.h>
|
||||||
|
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/IOFile.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "VideoCommon/Assets/MaterialAsset.h"
|
#include "VideoCommon/Assets/MaterialAsset.h"
|
||||||
|
#include "VideoCommon/Assets/MeshAsset.h"
|
||||||
#include "VideoCommon/Assets/ShaderAsset.h"
|
#include "VideoCommon/Assets/ShaderAsset.h"
|
||||||
#include "VideoCommon/Assets/TextureAsset.h"
|
#include "VideoCommon/Assets/TextureAsset.h"
|
||||||
#include "VideoCommon/RenderState.h"
|
#include "VideoCommon/RenderState.h"
|
||||||
@ -220,6 +223,110 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadMaterial(const As
|
|||||||
return LoadInfo{json_data.size(), GetLastAssetWriteTime(asset_id)};
|
return LoadInfo{json_data.size(), GetLastAssetWriteTime(asset_id)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadMesh(const AssetID& asset_id,
|
||||||
|
MeshData* data)
|
||||||
|
{
|
||||||
|
const auto asset_map = GetAssetMapForID(asset_id);
|
||||||
|
|
||||||
|
// Asset map for a mesh is the mesh and some metadata
|
||||||
|
if (asset_map.size() != 2)
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have two files mapped!", asset_id);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto metadata = asset_map.find("metadata");
|
||||||
|
const auto mesh = asset_map.find("mesh");
|
||||||
|
if (metadata == asset_map.end())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a metadata entry mapped!", asset_id);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh == asset_map.end())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a mesh entry mapped!", asset_id);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t metadata_size;
|
||||||
|
{
|
||||||
|
std::error_code ec;
|
||||||
|
metadata_size = std::filesystem::file_size(metadata->second, ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset '{}' error - failed to get mesh metadata file size with error '{}'!",
|
||||||
|
asset_id, ec);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::size_t mesh_size;
|
||||||
|
{
|
||||||
|
std::error_code ec;
|
||||||
|
mesh_size = std::filesystem::file_size(mesh->second, ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to get mesh file size with error '{}'!",
|
||||||
|
asset_id, ec);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto approx_mem_size = metadata_size + mesh_size;
|
||||||
|
|
||||||
|
File::IOFile file(PathToString(mesh->second), "rb");
|
||||||
|
if (!file.IsOpen())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to open mesh file '{}'!", asset_id,
|
||||||
|
PathToString(mesh->second));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> bytes;
|
||||||
|
bytes.reserve(file.GetSize());
|
||||||
|
file.ReadBytes(bytes.data(), file.GetSize());
|
||||||
|
if (!MeshData::FromDolphinMesh(bytes, data))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the mesh file '{}'!", asset_id,
|
||||||
|
PathToString(mesh->second));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string json_data;
|
||||||
|
if (!File::ReadFileToString(PathToString(metadata->second), json_data))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the json file '{}'!", asset_id,
|
||||||
|
PathToString(metadata->second));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
picojson::value root;
|
||||||
|
const auto error = picojson::parse(root, json_data);
|
||||||
|
|
||||||
|
if (!error.empty())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset '{}' error - failed to load the json file '{}', due to parse error: {}",
|
||||||
|
asset_id, PathToString(metadata->second), error);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!root.is<picojson::object>())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(
|
||||||
|
VIDEO,
|
||||||
|
"Asset '{}' error - failed to load the json file '{}', due to root not being an object!",
|
||||||
|
asset_id, PathToString(metadata->second));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& root_obj = root.get<picojson::object>();
|
||||||
|
|
||||||
|
if (!MeshData::FromJson(asset_id, root_obj, data))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return LoadInfo{approx_mem_size, GetLastAssetWriteTime(asset_id)};
|
||||||
|
}
|
||||||
|
|
||||||
CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadTexture(const AssetID& asset_id,
|
CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadTexture(const AssetID& asset_id,
|
||||||
TextureData* data)
|
TextureData* data)
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@ public:
|
|||||||
LoadInfo LoadTexture(const AssetID& asset_id, TextureData* data) override;
|
LoadInfo LoadTexture(const AssetID& asset_id, TextureData* data) override;
|
||||||
LoadInfo LoadPixelShader(const AssetID& asset_id, PixelShaderData* data) override;
|
LoadInfo LoadPixelShader(const AssetID& asset_id, PixelShaderData* data) override;
|
||||||
LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) override;
|
LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) override;
|
||||||
|
LoadInfo LoadMesh(const AssetID& asset_id, MeshData* data) override;
|
||||||
|
|
||||||
// Gets the latest time from amongst all the files in the asset map
|
// Gets the latest time from amongst all the files in the asset map
|
||||||
TimeType GetLastAssetWriteTime(const AssetID& asset_id) const override;
|
TimeType GetLastAssetWriteTime(const AssetID& asset_id) const override;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "Common/IOFile.h"
|
#include "Common/IOFile.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
#include "VideoCommon/Assets/CustomAssetLibrary.h"
|
||||||
|
|
||||||
namespace VideoCommon
|
namespace VideoCommon
|
||||||
{
|
{
|
||||||
@ -645,4 +646,18 @@ bool MeshData::FromGLTF(std::string_view gltf_file, MeshData* data)
|
|||||||
ERROR_LOG_FMT(VIDEO, "GLTF '{}' has invalid extension", gltf_file);
|
ERROR_LOG_FMT(VIDEO, "GLTF '{}' has invalid extension", gltf_file);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomAssetLibrary::LoadInfo MeshAsset::LoadImpl(const CustomAssetLibrary::AssetID& asset_id)
|
||||||
|
{
|
||||||
|
auto potential_data = std::make_shared<MeshData>();
|
||||||
|
const auto loaded_info = m_owning_library->LoadMesh(asset_id, potential_data.get());
|
||||||
|
if (loaded_info.m_bytes_loaded == 0)
|
||||||
|
return {};
|
||||||
|
{
|
||||||
|
std::lock_guard lk(m_data_lock);
|
||||||
|
m_loaded = true;
|
||||||
|
m_data = std::move(potential_data);
|
||||||
|
}
|
||||||
|
return loaded_info;
|
||||||
|
}
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
@ -57,4 +57,13 @@ struct MeshData
|
|||||||
std::map<std::string, CustomAssetLibrary::AssetID, std::less<>>
|
std::map<std::string, CustomAssetLibrary::AssetID, std::less<>>
|
||||||
m_mesh_material_to_material_asset_id;
|
m_mesh_material_to_material_asset_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MeshAsset final : public CustomLoadableAsset<MeshData>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using CustomLoadableAsset::CustomLoadableAsset;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CustomAssetLibrary::LoadInfo LoadImpl(const CustomAssetLibrary::AssetID& asset_id) override;
|
||||||
|
};
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
Reference in New Issue
Block a user