From 2d53b7364363b8d32f62905dbdbff01531ebe06d Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Thu, 12 Jan 2023 12:54:01 -0800 Subject: [PATCH] VertexLoaderTester: Add assertions for position/binormal/tangent caches --- Source/Core/VideoCommon/VertexLoaderBase.cpp | 80 +++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/VertexLoaderBase.cpp b/Source/Core/VideoCommon/VertexLoaderBase.cpp index e8b38ba345..f04580a074 100644 --- a/Source/Core/VideoCommon/VertexLoaderBase.cpp +++ b/Source/Core/VideoCommon/VertexLoaderBase.cpp @@ -13,11 +13,13 @@ #include #include "Common/Assert.h" +#include "Common/BitUtils.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "VideoCommon/VertexLoader.h" +#include "VideoCommon/VertexLoaderManager.h" #include "VideoCommon/VertexLoader_Color.h" #include "VideoCommon/VertexLoader_Normal.h" #include "VideoCommon/VertexLoader_Position.h" @@ -61,8 +63,36 @@ public: buffer_a.resize(count * a->m_native_vtx_decl.stride + 4); buffer_b.resize(count * b->m_native_vtx_decl.stride + 4); - int count_a = a->RunVertices(src, buffer_a.data(), count); - int count_b = b->RunVertices(src, buffer_b.data(), count); + const std::array old_position_matrix_index_cache = + VertexLoaderManager::position_matrix_index_cache; + const std::array, 3> old_position_cache = + VertexLoaderManager::position_cache; + const std::array old_tangent_cache = VertexLoaderManager::tangent_cache; + const std::array old_binormal_cache = VertexLoaderManager::binormal_cache; + + const int count_a = a->RunVertices(src, buffer_a.data(), count); + + const std::array a_position_matrix_index_cache = + VertexLoaderManager::position_matrix_index_cache; + const std::array, 3> a_position_cache = + VertexLoaderManager::position_cache; + const std::array a_tangent_cache = VertexLoaderManager::tangent_cache; + const std::array a_binormal_cache = VertexLoaderManager::binormal_cache; + + // Reset state before running b + VertexLoaderManager::position_matrix_index_cache = old_position_matrix_index_cache; + VertexLoaderManager::position_cache = old_position_cache; + VertexLoaderManager::tangent_cache = old_tangent_cache; + VertexLoaderManager::binormal_cache = old_binormal_cache; + + const int count_b = b->RunVertices(src, buffer_b.data(), count); + + const std::array b_position_matrix_index_cache = + VertexLoaderManager::position_matrix_index_cache; + const std::array, 3> b_position_cache = + VertexLoaderManager::position_cache; + const std::array b_tangent_cache = VertexLoaderManager::tangent_cache; + const std::array b_binormal_cache = VertexLoaderManager::binormal_cache; ASSERT_MSG(VIDEO, count_a == count_b, "The two vertex loaders have loaded a different amount of vertices (a: {}, b: {}).", @@ -75,6 +105,52 @@ public: "\nVertex desc:\n{}\n\nVertex attr:\n{}", m_VtxDesc, m_VtxAttr); + ASSERT_MSG(VIDEO, a_position_matrix_index_cache == b_position_matrix_index_cache, + "Expected matching position matrix caches after loading (a: {}; b: {})", + fmt::join(a_position_matrix_index_cache, ", "), + fmt::join(b_position_matrix_index_cache, ", ")); + + // Some games (e.g. Donkey Kong Country Returns) have a few draws that contain NaN. + // Since NaN != NaN, we need to compare the bits instead. + const auto bit_equal = [](float a, float b) { + return Common::BitCast(a) == Common::BitCast(b); + }; + + // The last element is allowed to be garbage for SIMD overwrites. + // For XY, the last 2 are garbage. + const bool positions_match = [&] { + const size_t max_component = m_VtxAttr.g0.PosElements == CoordComponentCount::XYZ ? 3 : 2; + for (size_t vertex = 0; vertex < 3; vertex++) + { + if (!std::equal(a_position_cache[vertex].begin(), + a_position_cache[vertex].begin() + max_component, + b_position_cache[vertex].begin(), bit_equal)) + { + return false; + } + } + return true; + }(); + + ASSERT_MSG(VIDEO, positions_match, + "Expected matching position caches after loading (a: {} / {} / {}; b: {} / {} / {})", + fmt::join(a_position_cache[0], ", "), fmt::join(a_position_cache[1], ", "), + fmt::join(a_position_cache[2], ", "), fmt::join(b_position_cache[0], ", "), + fmt::join(b_position_cache[1], ", "), fmt::join(b_position_cache[2], ", ")); + + // The last element is allowed to be garbage for SIMD overwrites + ASSERT_MSG(VIDEO, + std::equal(a_tangent_cache.begin(), a_tangent_cache.begin() + 3, + b_tangent_cache.begin(), b_tangent_cache.begin() + 3, bit_equal), + "Expected matching tangent caches after loading (a: {}; b: {})", + fmt::join(a_tangent_cache, ", "), fmt::join(b_tangent_cache, ", ")); + + ASSERT_MSG(VIDEO, + std::equal(a_binormal_cache.begin(), a_binormal_cache.begin() + 3, + b_binormal_cache.begin(), b_binormal_cache.begin() + 3, bit_equal), + "Expected matching binormal caches after loading (a: {}; b: {})", + fmt::join(a_binormal_cache, ", "), fmt::join(b_binormal_cache, ", ")); + memcpy(dst, buffer_a.data(), count_a * m_native_vtx_decl.stride); m_numLoadedVertices += count; return count_a;