diff options
| author | rdenno <rhysdenno@gmail.com> | 2026-11-02 09:26:01 -0500 |
|---|---|---|
| committer | rdenno <rhysdenno@gmail.com> | 2026-11-02 09:26:01 -0500 |
| commit | 2786bdf580e41bf0ba6e2a6452db73c4f5b97ed2 (patch) | |
| tree | 2c59cf5d66b869af52f338f3dea6e679e590f7bb /src/tests/video_core/vertex_repack.cpp | |
| parent | 7ac108e2571d7cb39585c58994524131dd9d8c22 (diff) | |
| parent | c0cb3325e22756edb65c87d33ef298349ade0ad3 (diff) | |
Merge branch 'nx2-experimental' into fix/hw-shader-lowering
nx2-experimental lowers partial-mask TXD as well (Splatoon Raiders).
Keep its RZ second destination and this branch's odd register for a
lone third channel; take its wider F2I mode check with the .H1 source.
Assisted-by: Claude Opus 5.5 (conflict resolution)
Diffstat (limited to 'src/tests/video_core/vertex_repack.cpp')
| -rw-r--r-- | src/tests/video_core/vertex_repack.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/tests/video_core/vertex_repack.cpp b/src/tests/video_core/vertex_repack.cpp new file mode 100644 index 0000000000..6409be3ca4 --- /dev/null +++ b/src/tests/video_core/vertex_repack.cpp @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <catch2/catch_test_macros.hpp> +#include "video_core/renderer_vulkan/vertex_repack.h" + +namespace { +using Regs = Tegra::Engines::Maxwell3D::Regs; +using Size = Regs::VertexAttribute::Size; + +Regs MakeLayout() { + Regs regs{}; + for (auto& attr : regs.vertex_attrib_format) { + attr.constant.Assign(1); + } + regs.vertex_streams[0].stride.Assign(69); + auto& position = regs.vertex_attrib_format[0]; + position.constant.Assign(0); + position.size.Assign(Size::Size_R32_G32_B32); + auto& packed = regs.vertex_attrib_format[1]; + packed.constant.Assign(0); + packed.offset.Assign(65); + packed.size.Assign(Size::Size_A2_B10_G10_R10); + return regs; +} +} + +TEST_CASE("Vertex repacking preserves aligned fields and relocates packed tail", "[vertex_repack]") { + const auto regs = MakeLayout(); + const auto mask = Vulkan::VertexRepackMask(regs); + REQUIRE(mask == 1); + REQUIRE(Vulkan::RepackedVertexOffset(mask, 0, 0) == 0); + REQUIRE(Vulkan::RepackedVertexOffset(mask, 0, 64) == 64); + REQUIRE(Vulkan::RepackedVertexOffset(mask, 0, 65) == 68); + REQUIRE(Vulkan::RepackedVertexStride(mask, 0, 69) == 72); + REQUIRE(Vulkan::RepackedVertexStride(mask, 1, 16) == 16); +} + +TEST_CASE("Vertex repacking excludes overlapping and oversized attributes", "[vertex_repack]") { + auto regs = MakeLayout(); + auto& attr = regs.vertex_attrib_format[2]; + attr.constant.Assign(0); + attr.offset.Assign(64); + attr.size.Assign(Size::Size_R32); + REQUIRE(Vulkan::VertexRepackMask(regs) == 0); + attr.offset.Assign(68); + REQUIRE(Vulkan::VertexRepackMask(regs) == 0); + attr.constant.Assign(1); + REQUIRE(Vulkan::VertexRepackMask(regs) == 1); +} + +TEST_CASE("Vertex repacking ignores constant invalid formats", "[vertex_repack]") { + auto regs = MakeLayout(); + REQUIRE(Vulkan::VertexRepackMask(regs) == 1); + regs.vertex_attrib_format[2].constant.Assign(0); + REQUIRE(Vulkan::VertexRepackMask(regs) == 0); +} + +TEST_CASE("Vertex repacking selects bindings independently", "[vertex_repack]") { + auto regs = MakeLayout(); + regs.vertex_streams[31].stride.Assign(69); + auto& attr = regs.vertex_attrib_format[2]; + attr = regs.vertex_attrib_format[1]; + attr.buffer.Assign(31); + REQUIRE(Vulkan::VertexRepackMask(regs) == 0x80000001U); + regs.vertex_streams[0].stride.Assign(72); + REQUIRE(Vulkan::VertexRepackMask(regs) == 0x80000000U); + REQUIRE(Vulkan::RepackedVertexOffset(0x80000000U, 0, 65) == 65); +} + +TEST_CASE("Vertex repacking requires the captured tail and stride", "[vertex_repack]") { + auto regs = MakeLayout(); + regs.vertex_streams[0].stride.Assign(68); + REQUIRE(Vulkan::VertexRepackMask(regs) == 0); + regs.vertex_streams[0].stride.Assign(69); + regs.vertex_attrib_format[1].offset.Assign(64); + REQUIRE(Vulkan::VertexRepackMask(regs) == 0); +} + +TEST_CASE("Static vertex repacking requires explicit experimental opt-in", "[vertex_repack]") { + REQUIRE(Vulkan::VertexRepackInputSupported(true, false)); + REQUIRE_FALSE(Vulkan::VertexRepackInputSupported(false, false)); + REQUIRE(Vulkan::VertexRepackInputSupported(false, true)); +} + +TEST_CASE("Vertex repack planning keeps descriptor offsets aligned", "[vertex_repack]") { + for (const u32 alignment : {4U, 16U, 64U, 256U, 4096U}) { + for (const u32 offset : {0U, 1U, 3U, 255U, 4099U}) { + const auto plan = Vulkan::MakeVertexRepackParameters(offset, 70, alignment, 1U << 20, 65535); + REQUIRE(plan.has_value()); + REQUIRE(plan->source_base % alignment == 0); + REQUIRE(plan->source_base + plan->source_bias == offset); + REQUIRE(plan->vertices == 2); + REQUIRE(plan->output_size == 144); + REQUIRE(plan->source_range >= plan->source_bias + 70); + REQUIRE(plan->source_range % 4 == 0); + REQUIRE(plan->dispatch_groups == 1); + } + } +} + +TEST_CASE("Vertex repack planning rejects overflow and device-limit violations", "[vertex_repack]") { + REQUIRE_FALSE(Vulkan::MakeVertexRepackParameters(0, 0, 256, 1U << 20, 65535)); + REQUIRE_FALSE(Vulkan::MakeVertexRepackParameters(0, 69, 0, 1U << 20, 65535)); + REQUIRE_FALSE(Vulkan::MakeVertexRepackParameters(0, 69, 256, 71, 65535)); + REQUIRE_FALSE(Vulkan::MakeVertexRepackParameters(255, 69, 256, 323, 65535)); + REQUIRE_FALSE(Vulkan::MakeVertexRepackParameters(0, 69, 256, 1U << 20, 0)); + REQUIRE_FALSE(Vulkan::MakeVertexRepackParameters(0, 0xffffffffU, 256, ~u64{0}, 0xffffffffU)); + const auto one = Vulkan::MakeVertexRepackParameters(0, 69, 256, 72, 1); + REQUIRE(one.has_value()); + REQUIRE(one->source_range == 72); +} |
