diff --git a/Source/Core/VideoCommon/VertexLoader.cpp b/Source/Core/VideoCommon/VertexLoader.cpp index 7f7dbc9030..7876e050c2 100644 --- a/Source/Core/VideoCommon/VertexLoader.cpp +++ b/Source/Core/VideoCommon/VertexLoader.cpp @@ -548,6 +548,7 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) m_compiledCode = nullptr; m_numLoadedVertices = 0; m_VertexSize = 0; + m_native_vertex_format = nullptr; loop_counter = 0; VertexLoader_Normal::Init(); VertexLoader_Position::Init(); @@ -1035,3 +1036,22 @@ void VertexLoader::AppendToString(std::string *dest) const } dest->append(StringFromFormat(" - %i v\n", m_numLoadedVertices)); } + +NativeVertexFormat* VertexLoader::GetNativeVertexFormat() +{ + if (m_native_vertex_format) + return m_native_vertex_format; + auto& native = s_native_vertex_map[m_native_vtx_decl]; + if (!native) + { + auto raw_pointer = g_vertex_manager->CreateNativeVertexFormat(); + native = std::unique_ptr(raw_pointer); + native->Initialize(m_native_vtx_decl); + native->m_components = m_native_components; + } + m_native_vertex_format = native.get(); + return native.get(); + +} + +std::map> VertexLoader::s_native_vertex_map; diff --git a/Source/Core/VideoCommon/VertexLoader.h b/Source/Core/VideoCommon/VertexLoader.h index 7be8385879..0bca6f5e5c 100644 --- a/Source/Core/VideoCommon/VertexLoader.h +++ b/Source/Core/VideoCommon/VertexLoader.h @@ -8,6 +8,8 @@ // Metroid Prime: P I16-flt N I16-s16 T0 I16-u16 T1 i16-flt #include +#include +#include #include #include "Common/CommonTypes.h" @@ -114,6 +116,9 @@ public: void AppendToString(std::string *dest) const; int GetNumLoadedVerts() const { return m_numLoadedVertices; } + NativeVertexFormat* GetNativeVertexFormat(); + static void ClearNativeVertexFormatCache() { s_native_vertex_map.clear(); } + private: int m_VertexSize; // number of bytes of a raw GC vertex. Computed by CompileVertexTranslator. @@ -135,6 +140,9 @@ private: int m_numLoadedVertices; + NativeVertexFormat* m_native_vertex_format; + static std::map> s_native_vertex_map; + void SetVAT(const VAT& vat); void CompileVertexTranslator(); diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp index dbf22c9c3d..b3a1c97c3f 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -24,8 +25,7 @@ static int s_attr_dirty; // bitfield static NativeVertexFormat* s_current_vtx_fmt; -typedef std::pair VertexLoaderCacheItem; -static VertexLoaderCacheItem s_VertexLoaders[8]; +static VertexLoader* s_VertexLoaders[8]; namespace std { @@ -41,14 +41,13 @@ struct hash } -typedef std::unordered_map VertexLoaderMap; -typedef std::map> NativeVertexLoaderMap; +typedef std::unordered_map> VertexLoaderMap; namespace VertexLoaderManager { -static VertexLoaderMap s_VertexLoaderMap; -static NativeVertexLoaderMap s_native_vertex_map; +static std::mutex s_vertex_loader_map_lock; +static VertexLoaderMap s_vertex_loader_map; // TODO - change into array of pointers. Keep a map of all seen so far. void Init() @@ -56,20 +55,16 @@ void Init() MarkAllDirty(); for (auto& map_entry : s_VertexLoaders) { - map_entry.first = nullptr; - map_entry.second = nullptr; + map_entry = nullptr; } RecomputeCachedArraybases(); } void Shutdown() { - for (auto& map_entry : s_VertexLoaderMap) - { - delete map_entry.second.first; - } - s_VertexLoaderMap.clear(); - s_native_vertex_map.clear(); + std::lock_guard lk(s_vertex_loader_map_lock); + s_vertex_loader_map.clear(); + VertexLoader::ClearNativeVertexFormatCache(); } namespace @@ -87,14 +82,15 @@ struct entry void AppendListToString(std::string *dest) { + std::lock_guard lk(s_vertex_loader_map_lock); std::vector entries; size_t total_size = 0; - for (const auto& map_entry : s_VertexLoaderMap) + for (const auto& map_entry : s_vertex_loader_map) { entry e; - map_entry.second.first->AppendToString(&e.text); - e.num_verts = map_entry.second.first->GetNumLoadedVerts(); + map_entry.second->AppendToString(&e.text); + e.num_verts = map_entry.second->GetNumLoadedVerts(); entries.push_back(e); total_size += e.text.size() + 1; } @@ -111,54 +107,39 @@ void MarkAllDirty() s_attr_dirty = 0xff; } -static NativeVertexFormat* GetNativeVertexFormat(const PortableVertexDeclaration& format, - u32 components) -{ - auto& native = s_native_vertex_map[format]; - if (!native) - { - auto raw_pointer = g_vertex_manager->CreateNativeVertexFormat(); - native = std::unique_ptr(raw_pointer); - native->Initialize(format); - native->m_components = components; - } - return native.get(); -} - -static VertexLoaderCacheItem RefreshLoader(int vtx_attr_group) +static VertexLoader* RefreshLoader(int vtx_attr_group) { + VertexLoader* loader; if ((s_attr_dirty >> vtx_attr_group) & 1) { VertexLoaderUID uid(g_VtxDesc, g_VtxAttr[vtx_attr_group]); - VertexLoaderMap::iterator iter = s_VertexLoaderMap.find(uid); - if (iter != s_VertexLoaderMap.end()) + std::lock_guard lk(s_vertex_loader_map_lock); + VertexLoaderMap::iterator iter = s_vertex_loader_map.find(uid); + if (iter != s_vertex_loader_map.end()) { - s_VertexLoaders[vtx_attr_group] = iter->second; + loader = iter->second.get(); } else { - VertexLoader* loader = new VertexLoader(g_VtxDesc, g_VtxAttr[vtx_attr_group]); - - NativeVertexFormat* vtx_fmt = GetNativeVertexFormat( - loader->GetNativeVertexDeclaration(), - loader->GetNativeComponents()); - - s_VertexLoaderMap[uid] = std::make_pair(loader, vtx_fmt); - s_VertexLoaders[vtx_attr_group] = std::make_pair(loader, vtx_fmt); + loader = new VertexLoader(g_VtxDesc, g_VtxAttr[vtx_attr_group]); + s_vertex_loader_map[uid] = std::unique_ptr(loader); INCSTAT(stats.numVertexLoaders); } + s_VertexLoaders[vtx_attr_group] = loader; + s_attr_dirty &= ~(1 << vtx_attr_group); + } else { + loader = s_VertexLoaders[vtx_attr_group]; } - s_attr_dirty &= ~(1 << vtx_attr_group); - return s_VertexLoaders[vtx_attr_group]; + return loader; } bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size, bool skip_drawing) { if (!count) return true; - auto loader = RefreshLoader(vtx_attr_group); + VertexLoader* loader = RefreshLoader(vtx_attr_group); - size_t size = count * loader.first->GetVertexSize(); + size_t size = count * loader->GetVertexSize(); if (buf_size < size) return false; @@ -169,15 +150,18 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size, return true; } + NativeVertexFormat* native = loader->GetNativeVertexFormat(); + + // If the native vertex format changed, force a flush. - if (loader.second != s_current_vtx_fmt) + if (native != s_current_vtx_fmt) VertexManager::Flush(); - s_current_vtx_fmt = loader.second; + s_current_vtx_fmt = native; VertexManager::PrepareForAdditionalData(primitive, count, - loader.first->GetNativeVertexDeclaration().stride); + loader->GetNativeVertexDeclaration().stride); - loader.first->RunVertices(g_VtxAttr[vtx_attr_group], primitive, count); + loader->RunVertices(g_VtxAttr[vtx_attr_group], primitive, count); IndexGenerator::AddIndices(primitive, count); @@ -188,7 +172,7 @@ bool RunVertices(int vtx_attr_group, int primitive, int count, size_t buf_size, int GetVertexSize(int vtx_attr_group) { - return RefreshLoader(vtx_attr_group).first->GetVertexSize(); + return RefreshLoader(vtx_attr_group)->GetVertexSize(); } NativeVertexFormat* GetCurrentVertexFormat()