Files
decaf-emu/tests/gpu/tiling/cpu_tiling_test.cpp
Brett Lawson b8b41add42 gpu: Major refactor of retiler implementation.
This commit converges the CPU and GPU retiling
implementations to have a common interface.  It
also converges their actual implementations to
be the same for both, allowing debugging and
performance improvements to the retiler on CPU
before porting to GPU.  This commit also updates
the retiler testing to be a lot more consistent,
and also ensures that both tiling AND untiling
are behaving appropriately.
2019-12-05 07:01:17 -08:00

247 lines
8.3 KiB
C++

#include "tiling_tests.h"
#include "addrlib_helpers.h"
#include "test_helpers.h"
#include <common/align.h>
#include <libgpu/gpu7_tiling_cpu.h>
static inline void
compareTilingToAddrLib(const gpu7::tiling::SurfaceDescription& desc,
std::vector<uint8_t>& input,
uint32_t firstSlice,
uint32_t numSlices)
{
auto addrLib = AddrLib { };
auto alibUntiled = std::vector<uint8_t> { };
auto gpu7Untiled = std::vector<uint8_t> { };
auto alibTiled = std::vector<uint8_t> { };
auto gpu7Tiled = std::vector<uint8_t> { };
// Compute surface info
auto alibInfo = addrLib.computeSurfaceInfo(desc, 0, 0);
auto gpu7Info = gpu7::tiling::computeSurfaceInfo(desc, 0);
REQUIRE(gpu7Info.surfSize == alibInfo.surfSize);
REQUIRE(input.size() >= gpu7Info.surfSize);
alibUntiled.resize(alibInfo.surfSize);
alibTiled.resize(alibInfo.surfSize);
gpu7Untiled.resize(gpu7Info.surfSize);
gpu7Tiled.resize(gpu7Info.surfSize);
// AddrLib
{
addrLib.untileSlices(desc, 0, input.data(), alibUntiled.data(), firstSlice, numSlices);
addrLib.tileSlices(desc, 0, alibUntiled.data(), alibTiled.data(), firstSlice, numSlices);
}
// GPU7
{
auto retileInfo = gpu7::tiling::computeRetileInfo(gpu7Info);
auto tiledFirstSliceIndex = align_down(firstSlice, retileInfo.microTileThickness);
auto tiledSliceOffset = tiledFirstSliceIndex * retileInfo.thinSliceBytes;
auto untiledSliceOffset = firstSlice * retileInfo.thinSliceBytes;
gpu7::tiling::cpu::untile(retileInfo,
gpu7Untiled.data() + untiledSliceOffset,
input.data() + tiledSliceOffset,
firstSlice, numSlices);
gpu7::tiling::cpu::tile(retileInfo,
gpu7Untiled.data() + untiledSliceOffset,
gpu7Tiled.data() + tiledSliceOffset,
firstSlice, numSlices);
}
CHECK(compareImages(gpu7Untiled, alibUntiled));
CHECK(compareImages(gpu7Tiled, alibTiled));
}
TEST_CASE("cpuTiling")
{
for (auto& layout : sTestLayout) {
SECTION(fmt::format("{}x{}x{} s{}n{}",
layout.width, layout.height, layout.depth,
layout.testFirstSlice, layout.testNumSlices))
{
for (auto& mode : sTestTilingMode) {
SECTION(fmt::format("{}", tileModeToString(mode.tileMode)))
{
for (auto& format : sTestFormats) {
SECTION(fmt::format("{}bpp{}", format.bpp, format.depth ? " depth" : ""))
{
auto surface = gpu7::tiling::SurfaceDescription { };
surface.tileMode = mode.tileMode;
surface.format = format.format;
surface.bpp = format.bpp;
surface.width = layout.width;
surface.height = layout.height;
surface.numSlices = layout.depth;
surface.numSamples = 1u;
surface.numLevels = 1u;
surface.bankSwizzle = 0u;
surface.pipeSwizzle = 0u;
surface.dim = gpu7::tiling::SurfaceDim::Texture2DArray;
surface.use = format.depth ?
gpu7::tiling::SurfaceUse::DepthBuffer :
gpu7::tiling::SurfaceUse::None;
compareTilingToAddrLib(surface,
sRandomData,
layout.testFirstSlice,
layout.testNumSlices);
}
}
}
}
}
}
}
struct ALibPendingCpuPerfEntry
{
gpu7::tiling::SurfaceDescription desc;
uint32_t firstSlice;
uint32_t numSlices;
ADDR_COMPUTE_SURFACE_INFO_OUTPUT info;
};
TEST_CASE("alibTilingPerf", "[!benchmark]")
{
// Set up AddrLib to generate data to test against
auto addrLib = AddrLib { };
// Get some random data to use
auto& untiled = sRandomData;
// Some place to store pending tests
std::vector<ALibPendingCpuPerfEntry> pendingTests;
// Generate all the test cases to run
auto& layout = sPerfTestLayout;
for (auto& mode : sTestTilingMode) {
for (auto& format : sTestFormats) {
auto surface = gpu7::tiling::SurfaceDescription {};
surface.tileMode = mode.tileMode;
surface.format = format.format;
surface.bpp = format.bpp;
surface.width = layout.width;
surface.height = layout.height;
surface.numSlices = layout.depth;
surface.numSamples = 1u;
surface.numLevels = 1u;
surface.bankSwizzle = 0u;
surface.pipeSwizzle = 0u;
surface.dim = gpu7::tiling::SurfaceDim::Texture2DArray;
surface.use = format.depth ?
gpu7::tiling::SurfaceUse::DepthBuffer :
gpu7::tiling::SurfaceUse::None;
auto info = addrLib.computeSurfaceInfo(surface, 0, 0);
ALibPendingCpuPerfEntry test;
test.desc = surface;
test.info = info;
test.firstSlice = layout.testFirstSlice;
test.numSlices = layout.testNumSlices;
pendingTests.push_back(test);
}
}
auto addrLibImage = std::vector<uint8_t> { };
addrLibImage.resize(untiled.size());
auto benchTitle = fmt::format("processing ({} retiles)", pendingTests.size());
BENCHMARK(benchTitle)
{
for (auto& test : pendingTests) {
// Compare image
addrLib.untileSlices(test.desc, 0,
untiled.data(), addrLibImage.data(),
test.firstSlice, test.numSlices);
}
}
}
struct PendingCpuPerfEntry
{
gpu7::tiling::SurfaceDescription desc;
uint32_t firstSlice;
uint32_t numSlices;
gpu7::tiling::SurfaceInfo info;
};
TEST_CASE("cpuTilingPerf", "[!benchmark]")
{
// Set up AddrLib to generate data to test against
auto addrLib = AddrLib { };
// Get some random data to use
auto& untiled = sRandomData;
// Some place to store pending tests
std::vector<PendingCpuPerfEntry> pendingTests;
// Generate all the test cases to run
auto& layout = sPerfTestLayout;
for (auto& mode : sTestTilingMode) {
for (auto& format : sTestFormats) {
auto surface = gpu7::tiling::SurfaceDescription {};
surface.tileMode = mode.tileMode;
surface.format = format.format;
surface.bpp = format.bpp;
surface.width = layout.width;
surface.height = layout.height;
surface.numSlices = layout.depth;
surface.numSamples = 1u;
surface.numLevels = 1u;
surface.bankSwizzle = 0u;
surface.pipeSwizzle = 0u;
surface.dim = gpu7::tiling::SurfaceDim::Texture2DArray;
surface.use = format.depth ?
gpu7::tiling::SurfaceUse::DepthBuffer :
gpu7::tiling::SurfaceUse::None;
auto info = gpu7::tiling::computeSurfaceInfo(surface, 0);
PendingCpuPerfEntry test;
test.desc = surface;
test.info = info;
test.firstSlice = layout.testFirstSlice;
test.numSlices = layout.testNumSlices;
pendingTests.push_back(test);
}
}
auto tiledImage = std::vector<uint8_t> { };
tiledImage.resize(untiled.size());
static constexpr auto TestIterMulti = 10;
auto benchTitle = fmt::format("processing ({} retiles)", pendingTests.size() * TestIterMulti);
BENCHMARK(benchTitle)
{
for (auto i = 0; i < TestIterMulti; ++i) {
for (auto& test : pendingTests) {
auto retileInfo = gpu7::tiling::computeRetileInfo(test.info);
auto tiledFirstSliceIndex = align_down(test.firstSlice, retileInfo.microTileThickness);
auto tiledSliceOffset = tiledFirstSliceIndex * retileInfo.thinSliceBytes;
auto untiledSliceOffset = test.firstSlice * retileInfo.thinSliceBytes;
gpu7::tiling::cpu::untile(retileInfo,
untiled.data() + untiledSliceOffset,
tiledImage.data() + tiledSliceOffset,
test.firstSlice,
test.numSlices);
}
}
}
}