summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2023-06-03 12:24:02 +0200
committerGitHub <noreply@github.com>2023-06-03 12:24:02 +0200
commit3245786af7ca5d1ea7c4ef4f71aea07f5d7bf7da (patch)
tree73c44ea37bcc5becd5fbc7545659b6266a0b48de /Source/Core/VideoCommon
parentd03e09c8fd911d1b4e66184ceedbeca989b75a0c (diff)
parent58d383b30b65e0e23f85e6a3a1bc5670966575eb (diff)
Merge pull request #11880 from iwubcode/race_condition_asset
VideoCommon: prevent potential data issue when reloading Asset data
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/Assets/CustomAsset.h8
-rw-r--r--Source/Core/VideoCommon/Assets/TextureAsset.cpp12
2 files changed, 14 insertions, 6 deletions
diff --git a/Source/Core/VideoCommon/Assets/CustomAsset.h b/Source/Core/VideoCommon/Assets/CustomAsset.h
index d3ba5226da..1f4d5061c1 100644
--- a/Source/Core/VideoCommon/Assets/CustomAsset.h
+++ b/Source/Core/VideoCommon/Assets/CustomAsset.h
@@ -64,7 +64,11 @@ class CustomLoadableAsset : public CustomAsset
public:
using CustomAsset::CustomAsset;
- const UnderlyingType* GetData() const
+ // Callees should understand that the type returned is
+ // a local copy and 'GetData()' needs to be called
+ // to ensure the latest copy is available if
+ // they want to handle reloads
+ [[nodiscard]] std::shared_ptr<UnderlyingType> GetData() const
{
std::lock_guard lk(m_lock);
if (m_loaded)
@@ -75,7 +79,7 @@ public:
protected:
bool m_loaded = false;
mutable std::mutex m_lock;
- UnderlyingType m_data;
+ std::shared_ptr<UnderlyingType> m_data;
};
} // namespace VideoCommon
diff --git a/Source/Core/VideoCommon/Assets/TextureAsset.cpp b/Source/Core/VideoCommon/Assets/TextureAsset.cpp
index fd27ee80b6..21f897fc19 100644
--- a/Source/Core/VideoCommon/Assets/TextureAsset.cpp
+++ b/Source/Core/VideoCommon/Assets/TextureAsset.cpp
@@ -10,20 +10,24 @@ namespace VideoCommon
CustomAssetLibrary::LoadInfo RawTextureAsset::LoadImpl(const CustomAssetLibrary::AssetID& asset_id)
{
std::lock_guard lk(m_lock);
- const auto loaded_info = m_owning_library->LoadTexture(asset_id, &m_data);
+ auto potential_data = std::make_shared<CustomTextureData>();
+ const auto loaded_info = m_owning_library->LoadTexture(asset_id, potential_data.get());
if (loaded_info.m_bytes_loaded == 0)
return {};
m_loaded = true;
+ m_data = std::move(potential_data);
return loaded_info;
}
CustomAssetLibrary::LoadInfo GameTextureAsset::LoadImpl(const CustomAssetLibrary::AssetID& asset_id)
{
std::lock_guard lk(m_lock);
- const auto loaded_info = m_owning_library->LoadGameTexture(asset_id, &m_data);
+ auto potential_data = std::make_shared<CustomTextureData>();
+ const auto loaded_info = m_owning_library->LoadGameTexture(asset_id, potential_data.get());
if (loaded_info.m_bytes_loaded == 0)
return {};
m_loaded = true;
+ m_data = std::move(potential_data);
return loaded_info;
}
@@ -39,7 +43,7 @@ bool GameTextureAsset::Validate(u32 native_width, u32 native_height) const
return false;
}
- if (m_data.m_levels.empty())
+ if (m_data->m_levels.empty())
{
ERROR_LOG_FMT(VIDEO,
"Game texture can't be validated for asset '{}' because no data was available.",
@@ -49,7 +53,7 @@ bool GameTextureAsset::Validate(u32 native_width, u32 native_height) const
// Verify that the aspect ratio of the texture hasn't changed, as this could have
// side-effects.
- const VideoCommon::CustomTextureData::Level& first_mip = m_data.m_levels[0];
+ const VideoCommon::CustomTextureData::Level& first_mip = m_data->m_levels[0];
if (first_mip.width * native_height != first_mip.height * native_width)
{
ERROR_LOG_FMT(