Merge pull request #11991 from iwubcode/tcache_multiple_texture_dependencies

VideoCommon: allow multiple texture assets to associate with a texture cache entry
This commit is contained in:
Admiral H. Curtiss 2023-07-02 20:14:32 +02:00 committed by GitHub
commit 6d7bf60071
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 32 deletions

View File

@ -263,11 +263,16 @@ void TextureCacheBase::SetBackupConfig(const VideoConfig& config)
bool TextureCacheBase::DidLinkedAssetsChange(const TCacheEntry& entry) bool TextureCacheBase::DidLinkedAssetsChange(const TCacheEntry& entry)
{ {
if (!entry.linked_asset.m_asset) for (const auto& cached_asset : entry.linked_game_texture_assets)
return false; {
if (cached_asset.m_asset)
{
if (cached_asset.m_asset->GetLastLoadedTime() > cached_asset.m_cached_write_time)
return true;
}
}
const auto last_asset_write_time = entry.linked_asset.m_asset->GetLastLoadedTime(); return false;
return last_asset_write_time > entry.linked_asset.m_cached_write_time;
} }
RcTcacheEntry TextureCacheBase::ApplyPaletteToEntry(RcTcacheEntry& entry, const u8* palette, RcTcacheEntry TextureCacheBase::ApplyPaletteToEntry(RcTcacheEntry& entry, const u8* palette,
@ -1590,8 +1595,8 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
InvalidateTexture(oldest_entry); InvalidateTexture(oldest_entry);
} }
VideoCommon::CachedAsset<VideoCommon::GameTextureAsset> cached_texture_asset; std::vector<VideoCommon::CachedAsset<VideoCommon::GameTextureAsset>> cached_game_assets;
std::shared_ptr<VideoCommon::CustomTextureData> data = nullptr; std::vector<std::shared_ptr<VideoCommon::CustomTextureData>> data_for_assets;
bool has_arbitrary_mipmaps = false; bool has_arbitrary_mipmaps = false;
std::shared_ptr<HiresTexture> hires_texture; std::shared_ptr<HiresTexture> hires_texture;
if (g_ActiveConfig.bHiresTextures) if (g_ActiveConfig.bHiresTextures)
@ -1599,31 +1604,37 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
hires_texture = HiresTexture::Search(texture_info); hires_texture = HiresTexture::Search(texture_info);
if (hires_texture) if (hires_texture)
{ {
data = hires_texture->GetAsset()->GetData(); auto asset = hires_texture->GetAsset();
cached_texture_asset = {hires_texture->GetAsset(), const auto loaded_time = asset->GetLastLoadedTime();
hires_texture->GetAsset()->GetLastLoadedTime()}; cached_game_assets.push_back(
VideoCommon::CachedAsset<VideoCommon::GameTextureAsset>{std::move(asset), loaded_time});
has_arbitrary_mipmaps = hires_texture->HasArbitraryMipmaps(); has_arbitrary_mipmaps = hires_texture->HasArbitraryMipmaps();
}
}
for (auto& cached_asset : cached_game_assets)
{
auto data = cached_asset.m_asset->GetData();
if (data) if (data)
{ {
if (!hires_texture->GetAsset()->Validate(texture_info.GetRawWidth(), if (cached_asset.m_asset->Validate(texture_info.GetRawWidth(), texture_info.GetRawHeight()))
texture_info.GetRawHeight()))
{ {
data = nullptr; data_for_assets.push_back(std::move(data));
}
} }
} }
} }
auto entry = CreateTextureEntry( auto entry = CreateTextureEntry(
TextureCreationInfo{base_hash, full_hash, bytes_per_block, palette_size}, texture_info, TextureCreationInfo{base_hash, full_hash, bytes_per_block, palette_size}, texture_info,
textureCacheSafetyColorSampleSize, data.get(), has_arbitrary_mipmaps); textureCacheSafetyColorSampleSize, std::move(data_for_assets), has_arbitrary_mipmaps);
entry->linked_asset = std::move(cached_texture_asset); entry->linked_game_texture_assets = std::move(cached_game_assets);
return entry; return entry;
} }
RcTcacheEntry TextureCacheBase::CreateTextureEntry( RcTcacheEntry TextureCacheBase::CreateTextureEntry(
const TextureCreationInfo& creation_info, const TextureInfo& texture_info, const TextureCreationInfo& creation_info, const TextureInfo& texture_info,
const int safety_color_sample_size, const VideoCommon::CustomTextureData* custom_texture_data, const int safety_color_sample_size,
std::vector<std::shared_ptr<VideoCommon::CustomTextureData>> assets_data,
const bool custom_arbitrary_mipmaps) const bool custom_arbitrary_mipmaps)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
@ -1633,20 +1644,33 @@ RcTcacheEntry TextureCacheBase::CreateTextureEntry(
#endif #endif
RcTcacheEntry entry; RcTcacheEntry entry;
if (custom_texture_data && custom_texture_data->m_levels.size() >= 1) if (!assets_data.empty())
{ {
const u32 texLevels = no_mips ? 1 : (u32)custom_texture_data->m_levels.size(); const auto calculate_max_levels = [&]() {
const auto& first_level = custom_texture_data->m_levels[0]; const auto max_element = std::max_element(
const TextureConfig config(first_level.width, first_level.height, texLevels, 1, 1, assets_data.begin(), assets_data.end(), [](const auto& lhs, const auto& rhs) {
first_level.format, 0); return lhs->m_levels.size() < rhs->m_levels.size();
});
return max_element->get()->m_levels.size();
};
const u32 texLevels = no_mips ? 1 : (u32)calculate_max_levels();
const auto& first_level = assets_data[0]->m_levels[0];
const TextureConfig config(first_level.width, first_level.height, texLevels,
static_cast<u32>(assets_data.size()), 1, first_level.format, 0);
entry = AllocateCacheEntry(config); entry = AllocateCacheEntry(config);
if (!entry) [[unlikely]] if (!entry) [[unlikely]]
return entry; return entry;
for (u32 level_index = 0; level_index != texLevels; ++level_index) for (u32 data_index = 0; data_index < static_cast<u32>(assets_data.size()); data_index++)
{ {
const auto& level = custom_texture_data->m_levels[level_index]; const auto asset = assets_data[data_index];
for (u32 level_index = 0;
level_index < std::min(texLevels, static_cast<u32>(asset->m_levels.size()));
++level_index)
{
const auto& level = asset->m_levels[level_index];
entry->texture->Load(level_index, level.width, level.height, level.row_length, entry->texture->Load(level_index, level.width, level.height, level.row_length,
level.data.data(), level.data.size()); level.data.data(), level.data.size(), data_index);
}
} }
entry->has_arbitrary_mips = custom_arbitrary_mipmaps; entry->has_arbitrary_mips = custom_arbitrary_mipmaps;

View File

@ -167,7 +167,7 @@ struct TCacheEntry
std::string texture_info_name = ""; std::string texture_info_name = "";
VideoCommon::CachedAsset<VideoCommon::GameTextureAsset> linked_asset; std::vector<VideoCommon::CachedAsset<VideoCommon::GameTextureAsset>> linked_game_texture_assets;
explicit TCacheEntry(std::unique_ptr<AbstractTexture> tex, explicit TCacheEntry(std::unique_ptr<AbstractTexture> tex,
std::unique_ptr<AbstractFramebuffer> fb); std::unique_ptr<AbstractFramebuffer> fb);
@ -346,9 +346,10 @@ private:
void SetBackupConfig(const VideoConfig& config); void SetBackupConfig(const VideoConfig& config);
RcTcacheEntry CreateTextureEntry(const TextureCreationInfo& creation_info, RcTcacheEntry
const TextureInfo& texture_info, int safety_color_sample_size, CreateTextureEntry(const TextureCreationInfo& creation_info, const TextureInfo& texture_info,
const VideoCommon::CustomTextureData* custom_texture_data, int safety_color_sample_size,
std::vector<std::shared_ptr<VideoCommon::CustomTextureData>> assets_data,
bool custom_arbitrary_mipmaps); bool custom_arbitrary_mipmaps);
RcTcacheEntry GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride); RcTcacheEntry GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride);