VideoCommon: instead of using 'CustomTextureData' directly, use 'TextureData' for texture assets, this allows us to provide additional metadata for textures. Such as a sampler or type information (to distinguish cube maps)

This commit is contained in:
iwubcode
2023-09-06 00:16:26 -05:00
parent 1b7a590b4b
commit 0e8f8ea930
13 changed files with 138 additions and 93 deletions

View File

@ -12,6 +12,7 @@
#include "Common/StringUtil.h"
#include "VideoCommon/Assets/MaterialAsset.h"
#include "VideoCommon/Assets/ShaderAsset.h"
#include "VideoCommon/Assets/TextureAsset.h"
namespace VideoCommon
{
@ -219,66 +220,126 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadMaterial(const As
}
CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadTexture(const AssetID& asset_id,
CustomTextureData* data)
TextureData* data)
{
const auto asset_map = GetAssetMapForID(asset_id);
// Raw texture is expected to have one asset mapped
if (asset_map.empty() || asset_map.size() > 1)
// Texture can optionally have a metadata file as well
if (asset_map.empty() || asset_map.size() > 2)
{
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - raw texture expected to have one file mapped!",
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - raw texture expected to have one or two files mapped!",
asset_id);
return {};
}
const auto& asset_path = asset_map.begin()->second;
std::error_code ec;
const auto last_loaded_time = std::filesystem::last_write_time(asset_path, ec);
if (ec)
const auto metadata = asset_map.find("metadata");
const auto texture_path = asset_map.find("texture");
if (texture_path == asset_map.end())
{
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to get last write time with error '{}'!",
asset_id, ec);
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a texture entry mapped!", asset_id);
return {};
}
auto ext = PathToString(asset_path.extension());
std::size_t metadata_size = 0;
if (metadata != asset_map.end())
{
std::error_code ec;
metadata_size = std::filesystem::file_size(metadata->second, ec);
if (ec)
{
ERROR_LOG_FMT(VIDEO,
"Asset '{}' error - failed to get texture metadata file size with error '{}'!",
asset_id, ec);
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 (!TextureData::FromJson(asset_id, root_obj, data))
{
return {};
}
}
else
{
data->m_type = TextureData::Type::Type_Texture2D;
}
auto ext = PathToString(texture_path->second.extension());
Common::ToLower(&ext);
if (ext == ".dds")
{
if (!LoadDDSTexture(data, PathToString(asset_path)))
if (!LoadDDSTexture(&data->m_texture, PathToString(texture_path->second)))
{
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - could not load dds texture!", asset_id);
return {};
}
if (data->m_slices.empty()) [[unlikely]]
data->m_slices.push_back({});
if (data->m_texture.m_slices.empty()) [[unlikely]]
data->m_texture.m_slices.push_back({});
if (!LoadMips(asset_path, &data->m_slices[0]))
if (!LoadMips(texture_path->second, &data->m_texture.m_slices[0]))
return {};
return LoadInfo{GetAssetSize(*data), FileTimeToSysTime(last_loaded_time)};
return LoadInfo{GetAssetSize(data->m_texture) + metadata_size, GetLastAssetWriteTime(asset_id)};
}
else if (ext == ".png")
{
// If we have no slices, create one
if (data->m_slices.empty())
data->m_slices.push_back({});
// PNG could support more complicated texture types in the future
// but for now just error
if (data->m_type != TextureData::Type::Type_Texture2D)
{
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - PNG is not supported for texture type '{}'!",
asset_id, data->m_type);
return {};
}
auto& slice = data->m_slices[0];
// If we have no slices, create one
if (data->m_texture.m_slices.empty())
data->m_texture.m_slices.push_back({});
auto& slice = data->m_texture.m_slices[0];
// If we have no levels, create one to pass into LoadPNGTexture
if (slice.m_levels.empty())
slice.m_levels.push_back({});
if (!LoadPNGTexture(&slice.m_levels[0], PathToString(asset_path)))
if (!LoadPNGTexture(&slice.m_levels[0], PathToString(texture_path->second)))
{
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - could not load png texture!", asset_id);
return {};
}
if (!LoadMips(asset_path, &slice))
if (!LoadMips(texture_path->second, &slice))
return {};
return LoadInfo{GetAssetSize(*data), FileTimeToSysTime(last_loaded_time)};
return LoadInfo{GetAssetSize(data->m_texture) + metadata_size, GetLastAssetWriteTime(asset_id)};
}
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - extension '{}' unknown!", asset_id, ext);