diff options
| author | JMC47 <JMC4789@gmail.com> | 2022-09-19 19:47:37 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-19 19:47:37 -0400 |
| commit | 3b10bf04ac74bff9ce11e6140ddc552f94eb2b3e (patch) | |
| tree | fe34d1ffeb5b8548ebf56fd6f427f153f7cd5526 /Source/UnitTests/VideoCommon/VertexLoaderTest.cpp | |
| parent | 91b1faa36a04151ea1ffc813eb3539626633c34c (diff) | |
| parent | d80201a57f6433bf660be2a1aecd60b97ddb6599 (diff) | |
Merge pull request #10808 from Pokechu22/vertex-loader-direct-normals-with-index3
VideoCommon: Fix direct normal+tangent+binormal with index3 set
Diffstat (limited to 'Source/UnitTests/VideoCommon/VertexLoaderTest.cpp')
| -rw-r--r-- | Source/UnitTests/VideoCommon/VertexLoaderTest.cpp | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp b/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp index b12dad1661..5e3898ed28 100644 --- a/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp +++ b/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp @@ -366,3 +366,413 @@ TEST_F(VertexLoaderTest, LargeFloatVertexSpeed) for (int i = 0; i < 100; ++i) RunVertices(100000); } + +TEST_F(VertexLoaderTest, DirectAllComponents) +{ + m_vtx_desc.low.PosMatIdx = 1; + m_vtx_desc.low.Tex0MatIdx = 1; + m_vtx_desc.low.Tex1MatIdx = 1; + m_vtx_desc.low.Tex2MatIdx = 1; + m_vtx_desc.low.Tex3MatIdx = 1; + m_vtx_desc.low.Tex4MatIdx = 1; + m_vtx_desc.low.Tex5MatIdx = 1; + m_vtx_desc.low.Tex6MatIdx = 1; + m_vtx_desc.low.Tex7MatIdx = 1; + m_vtx_desc.low.Position = VertexComponentFormat::Direct; + m_vtx_desc.low.Normal = VertexComponentFormat::Direct; + m_vtx_desc.low.Color0 = VertexComponentFormat::Direct; + m_vtx_desc.low.Color1 = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex0Coord = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex1Coord = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex2Coord = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex3Coord = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex4Coord = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex5Coord = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex6Coord = VertexComponentFormat::Direct; + m_vtx_desc.high.Tex7Coord = VertexComponentFormat::Direct; + + m_vtx_attr.g0.PosElements = CoordComponentCount::XYZ; + m_vtx_attr.g0.PosFormat = ComponentFormat::Float; + m_vtx_attr.g0.NormalElements = NormalComponentCount::NTB; + m_vtx_attr.g0.NormalFormat = ComponentFormat::Float; + m_vtx_attr.g0.Color0Elements = ColorComponentCount::RGBA; + m_vtx_attr.g0.Color0Comp = ColorFormat::RGBA8888; + m_vtx_attr.g0.Color1Elements = ColorComponentCount::RGBA; + m_vtx_attr.g0.Color1Comp = ColorFormat::RGBA8888; + m_vtx_attr.g0.Tex0CoordElements = TexComponentCount::ST; + m_vtx_attr.g0.Tex0CoordFormat = ComponentFormat::Float; + m_vtx_attr.g1.Tex1CoordElements = TexComponentCount::ST; + m_vtx_attr.g1.Tex1CoordFormat = ComponentFormat::Float; + m_vtx_attr.g1.Tex2CoordElements = TexComponentCount::ST; + m_vtx_attr.g1.Tex2CoordFormat = ComponentFormat::Float; + m_vtx_attr.g1.Tex3CoordElements = TexComponentCount::ST; + m_vtx_attr.g1.Tex3CoordFormat = ComponentFormat::Float; + m_vtx_attr.g1.Tex4CoordElements = TexComponentCount::ST; + m_vtx_attr.g1.Tex4CoordFormat = ComponentFormat::Float; + m_vtx_attr.g2.Tex5CoordElements = TexComponentCount::ST; + m_vtx_attr.g2.Tex5CoordFormat = ComponentFormat::Float; + m_vtx_attr.g2.Tex6CoordElements = TexComponentCount::ST; + m_vtx_attr.g2.Tex6CoordFormat = ComponentFormat::Float; + m_vtx_attr.g2.Tex7CoordElements = TexComponentCount::ST; + m_vtx_attr.g2.Tex7CoordFormat = ComponentFormat::Float; + + CreateAndCheckSizes(129, 39 * sizeof(float)); + + // Pos matrix idx + Input<u8>(20); + // Tex matrix idx + Input<u8>(0); + Input<u8>(1); + Input<u8>(2); + Input<u8>(3); + Input<u8>(4); + Input<u8>(5); + Input<u8>(6); + Input<u8>(7); + // Position + Input(-1.0f); + Input(-2.0f); + Input(-3.0f); + // Normal + Input(-4.0f); + Input(-5.0f); + Input(-6.0f); + // Tangent + Input(-7.0f); + Input(-8.0f); + Input(-9.0f); + // Binormal + Input(-10.0f); + Input(-11.0f); + Input(-12.0f); + // Colors + Input<u32>(0x01234567); + Input<u32>(0x89abcdef); + // Texture coordinates + Input(0.1f); + Input(-0.9f); + Input(1.1f); + Input(-1.9f); + Input(2.1f); + Input(-2.9f); + Input(3.1f); + Input(-3.9f); + Input(4.1f); + Input(-4.9f); + Input(5.1f); + Input(-5.9f); + Input(6.1f); + Input(-6.9f); + Input(7.1f); + Input(-7.9f); + + RunVertices(1); + + // Position matrix + ASSERT_EQ(m_loader->m_native_vtx_decl.posmtx.offset, 0 * sizeof(float)); + EXPECT_EQ((m_dst.Read<u32, false>()), 20u); + // Position + ASSERT_EQ(m_loader->m_native_vtx_decl.position.offset, 1 * sizeof(float)); + ExpectOut(-1.0f); + ExpectOut(-2.0f); + ExpectOut(-3.0f); + // Normal + ASSERT_EQ(m_loader->m_native_vtx_decl.normals[0].offset, 4 * sizeof(float)); + ExpectOut(-4.0f); + ExpectOut(-5.0f); + ExpectOut(-6.0f); + // Tangent + ASSERT_EQ(m_loader->m_native_vtx_decl.normals[1].offset, 7 * sizeof(float)); + ExpectOut(-7.0f); + ExpectOut(-8.0f); + ExpectOut(-9.0f); + // Binormal + ASSERT_EQ(m_loader->m_native_vtx_decl.normals[2].offset, 10 * sizeof(float)); + ExpectOut(-10.0f); + ExpectOut(-11.0f); + ExpectOut(-12.0f); + // Colors + ASSERT_EQ(m_loader->m_native_vtx_decl.colors[0].offset, 13 * sizeof(float)); + EXPECT_EQ((m_dst.Read<u32, true>()), 0x01234567u); + ASSERT_EQ(m_loader->m_native_vtx_decl.colors[1].offset, 14 * sizeof(float)); + EXPECT_EQ((m_dst.Read<u32, true>()), 0x89abcdefu); + // Texture coordinates and matrices (interleaved) + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[0].offset, 15 * sizeof(float)); + ExpectOut(0.1f); // S + ExpectOut(-0.9f); // T + ExpectOut(0.0f); // matrix (yes, a float) + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[1].offset, 18 * sizeof(float)); + ExpectOut(1.1f); + ExpectOut(-1.9f); + ExpectOut(1.0f); + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[2].offset, 21 * sizeof(float)); + ExpectOut(2.1f); + ExpectOut(-2.9f); + ExpectOut(2.0f); + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[3].offset, 24 * sizeof(float)); + ExpectOut(3.1f); + ExpectOut(-3.9f); + ExpectOut(3.0f); + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[4].offset, 27 * sizeof(float)); + ExpectOut(4.1f); + ExpectOut(-4.9f); + ExpectOut(4.0f); + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[5].offset, 30 * sizeof(float)); + ExpectOut(5.1f); + ExpectOut(-5.9f); + ExpectOut(5.0f); + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[6].offset, 33 * sizeof(float)); + ExpectOut(6.1f); + ExpectOut(-6.9f); + ExpectOut(6.0f); + ASSERT_EQ(m_loader->m_native_vtx_decl.texcoords[7].offset, 36 * sizeof(float)); + ExpectOut(7.1f); + ExpectOut(-7.9f); + ExpectOut(7.0f); +} + +class VertexLoaderNormalTest + : public VertexLoaderTest, + public ::testing::WithParamInterface< + std::tuple<VertexComponentFormat, ComponentFormat, NormalComponentCount, bool>> +{ +}; +INSTANTIATE_TEST_CASE_P( + AllCombinations, VertexLoaderNormalTest, + ::testing::Combine( + ::testing::Values(VertexComponentFormat::NotPresent, VertexComponentFormat::Direct, + VertexComponentFormat::Index8, VertexComponentFormat::Index16), + ::testing::Values(ComponentFormat::UByte, ComponentFormat::Byte, ComponentFormat::UShort, + ComponentFormat::Short, ComponentFormat::Float), + ::testing::Values(NormalComponentCount::N, NormalComponentCount::NTB), + ::testing::Values(false, true))); + +TEST_P(VertexLoaderNormalTest, NormalAll) +{ + VertexComponentFormat addr; + ComponentFormat format; + NormalComponentCount elements; + bool index3; + std::tie(addr, format, elements, index3) = GetParam(); + + m_vtx_desc.low.Position = VertexComponentFormat::Direct; + m_vtx_attr.g0.PosFormat = ComponentFormat::Float; + m_vtx_attr.g0.PosElements = CoordComponentCount::XY; + m_vtx_attr.g0.PosFrac = 0; + m_vtx_desc.low.Normal = addr; + m_vtx_attr.g0.NormalFormat = format; + m_vtx_attr.g0.NormalElements = elements; + m_vtx_attr.g0.NormalIndex3 = index3; + + const u32 in_size = [&]() -> u32 { + if (addr == VertexComponentFormat::NotPresent) + return 0; + + if (IsIndexed(addr)) + { + const u32 base_size = (addr == VertexComponentFormat::Index8) ? 1 : 2; + if (elements == NormalComponentCount::NTB) + return (index3 ? 3 : 1) * base_size; + else + return 1 * base_size; + } + else + { + const u32 base_count = (elements == NormalComponentCount::NTB) ? 9 : 3; + const u32 base_size = GetElementSize(format); + return base_count * base_size; + } + }(); + const u32 out_size = [&]() -> u32 { + if (addr == VertexComponentFormat::NotPresent) + return 0; + + const u32 base_count = (elements == NormalComponentCount::NTB) ? 9 : 3; + return base_count * sizeof(float); + }(); + + CreateAndCheckSizes(2 * sizeof(float) + in_size, 2 * sizeof(float) + out_size); + + auto input_with_expected_type = [&](float value) { + switch (format) + { + case ComponentFormat::UByte: + Input<u8>(value * (1 << 7)); + break; + case ComponentFormat::Byte: + Input<s8>(value * (1 << 6)); + break; + case ComponentFormat::UShort: + Input<u16>(value * (1 << 15)); + break; + case ComponentFormat::Short: + Input<s16>(value * (1 << 14)); + break; + case ComponentFormat::Float: + default: + Input<float>(value); + break; + } + }; + + auto create_normal = [&](int counter_base) { + if (addr == VertexComponentFormat::Direct) + { + input_with_expected_type(counter_base / 32.f); + input_with_expected_type((counter_base + 1) / 32.f); + input_with_expected_type((counter_base + 2) / 32.f); + } + else if (addr == VertexComponentFormat::Index8) + { + // We set up arrays so that this works + Input<u8>(counter_base); + } + else if (addr == VertexComponentFormat::Index16) + { + Input<u16>(counter_base); + } + // Do nothing for NotPresent + }; + auto create_tangent_and_binormal = [&](int counter_base) { + if (IsIndexed(addr)) + { + // With NormalIndex3, specifying the same index 3 times should give the same result + // as specifying one index in non-index3 mode (as the index is biased by bytes). + // If index3 is disabled, we don't want to write any more indices. + if (index3) + { + // Tangent + create_normal(counter_base); + // Binormal + create_normal(counter_base); + } + } + else + { + // Tangent + create_normal(counter_base + 3); + // Binormal + create_normal(counter_base + 6); + } + }; + + // Create our two vertices + // Position 1 + Input(4.0f); + Input(8.0f); + // Normal 1 + create_normal(1); + if (elements == NormalComponentCount::NTB) + { + create_tangent_and_binormal(1); + } + + // Position 2 + Input(6.0f); + Input(12.0f); + // Normal 1 + create_normal(10); + if (elements == NormalComponentCount::NTB) + { + create_tangent_and_binormal(10); + } + + // Create an array for indexed representations + for (int i = 0; i < NUM_VERTEX_COMPONENT_ARRAYS; i++) + { + VertexLoaderManager::cached_arraybases[static_cast<CPArray>(i)] = m_src.GetPointer(); + g_main_cp_state.array_strides[static_cast<CPArray>(i)] = GetElementSize(format); + } + + for (int i = 0; i < 32; i++) + input_with_expected_type(i / 32.f); + + // Pre-fill these values to detect if they're modified + VertexLoaderManager::binormal_cache = {42.f, 43.f, 44.f, 45.f}; + VertexLoaderManager::tangent_cache = {46.f, 47.f, 48.f, 49.f}; + + RunVertices(2); + + // First vertex, position + ExpectOut(4.0f); + ExpectOut(8.0f); + if (addr != VertexComponentFormat::NotPresent) + { + // Normal + ExpectOut(1 / 32.f); + ExpectOut(2 / 32.f); + ExpectOut(3 / 32.f); + if (elements == NormalComponentCount::NTB) + { + // Tangent + ExpectOut(4 / 32.f); + ExpectOut(5 / 32.f); + ExpectOut(6 / 32.f); + // Binormal + ExpectOut(7 / 32.f); + ExpectOut(8 / 32.f); + ExpectOut(9 / 32.f); + } + } + + // Second vertex, position + ExpectOut(6.0f); + ExpectOut(12.0f); + if (addr != VertexComponentFormat::NotPresent) + { + // Normal + ExpectOut(10 / 32.f); + ExpectOut(11 / 32.f); + ExpectOut(12 / 32.f); + if (elements == NormalComponentCount::NTB) + { + // Tangent + ExpectOut(13 / 32.f); + ExpectOut(14 / 32.f); + ExpectOut(15 / 32.f); + // Binormal + ExpectOut(16 / 32.f); + ExpectOut(17 / 32.f); + ExpectOut(18 / 32.f); + + EXPECT_EQ(VertexLoaderManager::tangent_cache[0], 13 / 32.f); + EXPECT_EQ(VertexLoaderManager::tangent_cache[1], 14 / 32.f); + EXPECT_EQ(VertexLoaderManager::tangent_cache[2], 15 / 32.f); + // Last index is padding/junk + EXPECT_EQ(VertexLoaderManager::binormal_cache[0], 16 / 32.f); + EXPECT_EQ(VertexLoaderManager::binormal_cache[1], 17 / 32.f); + EXPECT_EQ(VertexLoaderManager::binormal_cache[2], 18 / 32.f); + } + } + + if (addr == VertexComponentFormat::NotPresent || elements == NormalComponentCount::N) + { + // Expect these to not be written + EXPECT_EQ(VertexLoaderManager::binormal_cache[0], 42.f); + EXPECT_EQ(VertexLoaderManager::binormal_cache[1], 43.f); + EXPECT_EQ(VertexLoaderManager::binormal_cache[2], 44.f); + EXPECT_EQ(VertexLoaderManager::binormal_cache[3], 45.f); + EXPECT_EQ(VertexLoaderManager::tangent_cache[0], 46.f); + EXPECT_EQ(VertexLoaderManager::tangent_cache[1], 47.f); + EXPECT_EQ(VertexLoaderManager::tangent_cache[2], 48.f); + EXPECT_EQ(VertexLoaderManager::tangent_cache[3], 49.f); + } +} + +// For gtest, which doesn't know about our fmt::formatters by default +static void PrintTo(const VertexComponentFormat& t, std::ostream* os) +{ + *os << fmt::to_string(t); +} +static void PrintTo(const ComponentFormat& t, std::ostream* os) +{ + *os << fmt::to_string(t); +} +static void PrintTo(const CoordComponentCount& t, std::ostream* os) +{ + *os << fmt::to_string(t); +} +static void PrintTo(const NormalComponentCount& t, std::ostream* os) +{ + *os << fmt::to_string(t); +} |
