summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/VertexLoaderManager.cpp
diff options
context:
space:
mode:
authorPokechu22 <Pokechu022@gmail.com>2022-05-17 13:42:31 -0700
committerPokechu22 <Pokechu022@gmail.com>2022-05-18 14:43:14 -0700
commit38a75f6a49706840edf7a6f5b94e224468ebbabd (patch)
treecccaaf943e5ee7e6806ec2ecf5f5b4b78149ad25 /Source/Core/VideoCommon/VertexLoaderManager.cpp
parent46bcdc4372209f343ff28994770c0666a0d6c3ac (diff)
Show a panic alert if the CP vertex config doesn't match the XF vertex config
This probably isn't triggered by real games, but it's possible to accidentally do it with libogc (which results in freezes on real hardware).
Diffstat (limited to 'Source/Core/VideoCommon/VertexLoaderManager.cpp')
-rw-r--r--Source/Core/VideoCommon/VertexLoaderManager.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp
index 7710b7cc20..eea5183a81 100644
--- a/Source/Core/VideoCommon/VertexLoaderManager.cpp
+++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp
@@ -16,6 +16,7 @@
#include "Common/EnumMap.h"
#include "Common/Logging/Log.h"
+#include "Core/DolphinAnalytics.h"
#include "Core/HW/Memmap.h"
#include "VideoCommon/BPMemory.h"
@@ -28,6 +29,7 @@
#include "VideoCommon/VertexLoaderBase.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VertexShaderManager.h"
+#include "VideoCommon/XFMemory.h"
namespace VertexLoaderManager
{
@@ -249,6 +251,78 @@ static VertexLoaderBase* RefreshLoader(int vtx_attr_group, bool preprocess = fal
return loader;
}
+static void CheckCPConfiguration(int vtx_attr_group)
+{
+ // Validate that the XF input configuration matches the CP configuration
+ u32 num_cp_colors = std::count_if(
+ g_main_cp_state.vtx_desc.low.Color.begin(), g_main_cp_state.vtx_desc.low.Color.end(),
+ [](auto format) { return format != VertexComponentFormat::NotPresent; });
+ u32 num_cp_tex_coords = std::count_if(
+ g_main_cp_state.vtx_desc.high.TexCoord.begin(), g_main_cp_state.vtx_desc.high.TexCoord.end(),
+ [](auto format) { return format != VertexComponentFormat::NotPresent; });
+
+ u32 num_cp_normals;
+ if (g_main_cp_state.vtx_desc.low.Normal == VertexComponentFormat::NotPresent)
+ num_cp_normals = 0;
+ else if (g_main_cp_state.vtx_attr[vtx_attr_group].g0.NormalElements == NormalComponentCount::NTB)
+ num_cp_normals = 3;
+ else
+ num_cp_normals = 1;
+
+ std::optional<u32> num_xf_normals;
+ switch (xfmem.invtxspec.numnormals)
+ {
+ case NormalCount::None:
+ num_xf_normals = 0;
+ break;
+ case NormalCount::Normal:
+ num_xf_normals = 1;
+ break;
+ case NormalCount::NormalTangentBinormal:
+ num_xf_normals = 3;
+ break;
+ default:
+ PanicAlertFmt("xfmem.invtxspec.numnormals is invalid: {}", xfmem.invtxspec.numnormals);
+ break;
+ }
+
+ if (num_cp_colors != xfmem.invtxspec.numcolors || num_cp_normals != num_xf_normals ||
+ num_cp_tex_coords != xfmem.invtxspec.numtextures)
+ {
+ PanicAlertFmt("Mismatched configuration between CP and XF stages - {}/{} colors, {}/{} "
+ "normals, {}/{} texture coordinates. Please report on the issue tracker.\n\n"
+ "VCD: {:08x} {:08x}\nVAT {}: {:08x} {:08x} {:08x}\nXF vertex spec: {:08x}",
+ num_cp_colors, xfmem.invtxspec.numcolors, num_cp_normals,
+ num_xf_normals.has_value() ? fmt::to_string(num_xf_normals.value()) : "invalid",
+ num_cp_tex_coords, xfmem.invtxspec.numtextures, g_main_cp_state.vtx_desc.low.Hex,
+ g_main_cp_state.vtx_desc.high.Hex, vtx_attr_group,
+ g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex,
+ g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex,
+ g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex, xfmem.invtxspec.hex);
+
+ // Analytics reporting so we can discover which games have this problem, that way when we
+ // eventually simulate the behavior we have test cases for it.
+ if (num_cp_colors != xfmem.invtxspec.numcolors)
+ {
+ DolphinAnalytics::Instance().ReportGameQuirk(
+ GameQuirk::MISMATCHED_GPU_COLORS_BETWEEN_CP_AND_XF);
+ }
+ if (num_cp_normals != num_xf_normals)
+ {
+ DolphinAnalytics::Instance().ReportGameQuirk(
+ GameQuirk::MISMATCHED_GPU_NORMALS_BETWEEN_CP_AND_XF);
+ }
+ if (num_cp_tex_coords != xfmem.invtxspec.numtextures)
+ {
+ DolphinAnalytics::Instance().ReportGameQuirk(
+ GameQuirk::MISMATCHED_GPU_TEX_COORDS_BETWEEN_CP_AND_XF);
+ }
+
+ // Don't bail out, though; we can still render something successfully
+ // (real hardware seems to hang in this case, though)
+ }
+}
+
int RunVertices(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int count, DataReader src,
bool is_preprocess)
{
@@ -265,6 +339,8 @@ int RunVertices(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int coun
if (is_preprocess)
return size;
+ 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)