summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/VertexLoaderManager.cpp
diff options
context:
space:
mode:
authorRobin Kertels <robin.kertels@gmail.com>2022-09-15 23:38:57 +0200
committerRobin Kertels <robin.kertels@gmail.com>2022-09-19 01:14:49 +0200
commita6c6ec012ce6d5355b776379ec8b2cbd94552cf3 (patch)
tree3b55335936334d03d8c7f971b92412da09f41dd1 /Source/Core/VideoCommon/VertexLoaderManager.cpp
parenta31e36aeb757d9b0515990becd65cd0b8561da26 (diff)
VertexLoaderManager: Clean up and slightly speed up with templates
Diffstat (limited to 'Source/Core/VideoCommon/VertexLoaderManager.cpp')
-rw-r--r--Source/Core/VideoCommon/VertexLoaderManager.cpp140
1 files changed, 69 insertions, 71 deletions
diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp
index 800cda7820..607de66bee 100644
--- a/Source/Core/VideoCommon/VertexLoaderManager.cpp
+++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp
@@ -54,7 +54,6 @@ Common::EnumMap<u8*, CPArray::TexCoord7> cached_arraybases;
BitSet8 g_main_vat_dirty;
BitSet8 g_preprocess_vat_dirty;
bool g_bases_dirty; // Main only
-u8 g_current_vat; // Main only
std::array<VertexLoaderBase*, CP_NUM_VAT_REG> g_main_vertex_loaders;
std::array<VertexLoaderBase*, CP_NUM_VAT_REG> g_preprocess_vertex_loaders;
@@ -78,7 +77,7 @@ void Clear()
void UpdateVertexArrayPointers()
{
// Anything to update?
- if (!g_bases_dirty)
+ if (!g_bases_dirty) [[likely]]
return;
// Some games such as Burnout 2 can put invalid addresses into
@@ -198,59 +197,50 @@ NativeVertexFormat* GetUberVertexFormat(const PortableVertexDeclaration& decl)
return GetOrCreateMatchingFormat(new_decl);
}
-static VertexLoaderBase* RefreshLoader(int vtx_attr_group, bool preprocess = false)
+namespace detail
{
- CPState* state = preprocess ? &g_preprocess_cp_state : &g_main_cp_state;
- BitSet8& attr_dirty = preprocess ? g_preprocess_vat_dirty : g_main_vat_dirty;
- auto& vertex_loaders = preprocess ? g_preprocess_vertex_loaders : g_main_vertex_loaders;
- g_current_vat = vtx_attr_group;
+template <bool IsPreprocess>
+VertexLoaderBase* GetOrCreateLoader(int vtx_attr_group)
+{
+ constexpr CPState* state = IsPreprocess ? &g_preprocess_cp_state : &g_main_cp_state;
+ constexpr BitSet8& attr_dirty = IsPreprocess ? g_preprocess_vat_dirty : g_main_vat_dirty;
+ constexpr auto& vertex_loaders =
+ IsPreprocess ? g_preprocess_vertex_loaders : g_main_vertex_loaders;
VertexLoaderBase* loader;
- if (attr_dirty[vtx_attr_group])
+
+ // We are not allowed to create a native vertex format on preprocessing as this is on the wrong
+ // thread
+ bool check_for_native_format = !IsPreprocess;
+
+ VertexLoaderUID uid(state->vtx_desc, state->vtx_attr[vtx_attr_group]);
+ std::lock_guard<std::mutex> lk(s_vertex_loader_map_lock);
+ VertexLoaderMap::iterator iter = s_vertex_loader_map.find(uid);
+ if (iter != s_vertex_loader_map.end())
{
- // We are not allowed to create a native vertex format on preprocessing as this is on the wrong
- // thread
- bool check_for_native_format = !preprocess;
-
- VertexLoaderUID uid(state->vtx_desc, state->vtx_attr[vtx_attr_group]);
- std::lock_guard<std::mutex> lk(s_vertex_loader_map_lock);
- VertexLoaderMap::iterator iter = s_vertex_loader_map.find(uid);
- if (iter != s_vertex_loader_map.end())
- {
- loader = iter->second.get();
- check_for_native_format &= !loader->m_native_vertex_format;
- }
- else
- {
- s_vertex_loader_map[uid] =
- VertexLoaderBase::CreateVertexLoader(state->vtx_desc, state->vtx_attr[vtx_attr_group]);
- loader = s_vertex_loader_map[uid].get();
- INCSTAT(g_stats.num_vertex_loaders);
- }
- if (check_for_native_format)
- {
- // search for a cached native vertex format
- const PortableVertexDeclaration& format = loader->m_native_vtx_decl;
- std::unique_ptr<NativeVertexFormat>& native = s_native_vertex_map[format];
- if (!native)
- native = g_renderer->CreateNativeVertexFormat(format);
- loader->m_native_vertex_format = native.get();
- }
- vertex_loaders[vtx_attr_group] = loader;
- attr_dirty[vtx_attr_group] = false;
+ loader = iter->second.get();
+ check_for_native_format &= !loader->m_native_vertex_format;
}
else
{
- loader = vertex_loaders[vtx_attr_group];
+ auto [it, added] = s_vertex_loader_map.try_emplace(
+ uid,
+ VertexLoaderBase::CreateVertexLoader(state->vtx_desc, state->vtx_attr[vtx_attr_group]));
+ loader = it->second.get();
+ INCSTAT(g_stats.num_vertex_loaders);
}
-
- // Lookup pointers for any vertex arrays.
- if (!preprocess)
- UpdateVertexArrayPointers();
-
+ if (check_for_native_format)
+ {
+ // search for a cached native vertex format
+ loader->m_native_vertex_format = GetOrCreateMatchingFormat(loader->m_native_vtx_decl);
+ }
+ vertex_loaders[vtx_attr_group] = loader;
+ attr_dirty[vtx_attr_group] = false;
return loader;
}
+} // namespace detail
+
static void CheckCPConfiguration(int vtx_attr_group)
{
// Validate that the XF input configuration matches the CP configuration
@@ -335,53 +325,61 @@ static void CheckCPConfiguration(int vtx_attr_group)
}
}
-int RunVertices(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int count, DataReader src,
- bool is_preprocess)
+template <bool IsPreprocess>
+int RunVertices(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int count, DataReader src)
{
if (count == 0)
return 0;
ASSERT(count > 0);
- VertexLoaderBase* loader = RefreshLoader(vtx_attr_group, is_preprocess);
+ VertexLoaderBase* loader = RefreshLoader<IsPreprocess>(vtx_attr_group);
int size = count * loader->m_vertex_size;
if ((int)src.size() < size)
return -1;
- if (is_preprocess)
- return size;
+ if constexpr (!IsPreprocess)
+ {
+ // Doing early return for the opposite case would be cleaner
+ // but triggers a false unreachable code warning in MSVC debug builds.
- CheckCPConfiguration(vtx_attr_group);
+ CheckCPConfiguration(vtx_attr_group);
- // If the native vertex format changed, force a flush.
- if (loader->m_native_vertex_format != s_current_vtx_fmt ||
- loader->m_native_components != g_current_components)
- {
- g_vertex_manager->Flush();
- }
- s_current_vtx_fmt = loader->m_native_vertex_format;
- g_current_components = loader->m_native_components;
- VertexShaderManager::SetVertexFormat(loader->m_native_components);
+ // If the native vertex format changed, force a flush.
+ if (loader->m_native_vertex_format != s_current_vtx_fmt ||
+ loader->m_native_components != g_current_components)
+ {
+ g_vertex_manager->Flush();
+ }
+ s_current_vtx_fmt = loader->m_native_vertex_format;
+ g_current_components = loader->m_native_components;
+ VertexShaderManager::SetVertexFormat(loader->m_native_components);
- // if cull mode is CULL_ALL, tell VertexManager to skip triangles and quads.
- // They still need to go through vertex loading, because we need to calculate a zfreeze refrence
- // slope.
- bool cullall = (bpmem.genMode.cullmode == CullMode::All &&
- primitive < OpcodeDecoder::Primitive::GX_DRAW_LINES);
+ // if cull mode is CULL_ALL, tell VertexManager to skip triangles and quads.
+ // They still need to go through vertex loading, because we need to calculate a zfreeze refrence
+ // slope.
+ bool cullall = (bpmem.genMode.cullmode == CullMode::All &&
+ primitive < OpcodeDecoder::Primitive::GX_DRAW_LINES);
- DataReader dst = g_vertex_manager->PrepareForAdditionalData(
- primitive, count, loader->m_native_vtx_decl.stride, cullall);
+ DataReader dst = g_vertex_manager->PrepareForAdditionalData(
+ primitive, count, loader->m_native_vtx_decl.stride, cullall);
- count = loader->RunVertices(src, dst, count);
+ count = loader->RunVertices(src, dst, count);
- g_vertex_manager->AddIndices(primitive, count);
- g_vertex_manager->FlushData(count, loader->m_native_vtx_decl.stride);
+ g_vertex_manager->AddIndices(primitive, count);
+ g_vertex_manager->FlushData(count, loader->m_native_vtx_decl.stride);
- ADDSTAT(g_stats.this_frame.num_prims, count);
- INCSTAT(g_stats.this_frame.num_primitive_joins);
+ ADDSTAT(g_stats.this_frame.num_prims, count);
+ INCSTAT(g_stats.this_frame.num_primitive_joins);
+ }
return size;
}
+template int RunVertices<false>(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int count,
+ DataReader src);
+template int RunVertices<true>(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int count,
+ DataReader src);
+
NativeVertexFormat* GetCurrentVertexFormat()
{
return s_current_vtx_fmt;