#include "GraphicsTests.hpp" #include "prx/libSceAgcDriver/Graphics/include/TextureTiling.hpp" #include #include namespace { using namespace AgcDriver::Graphics; template void reject(TAction action, std::string_view reason) { try { action(); } catch (const std::runtime_error& error) { Require(std::string_view(error.what()).find(reason) != std::string_view::npos, std::string("unexpected texture tiling test error: ") + error.what()); return; } throw std::runtime_error(std::string("expected texture tiling rejection: ") + std::string(reason)); } } void RunTextureTilingTests() { { const auto mips = ComputeMipLayout(TextureTileMode::kLinear, 1, 4, 4, 2); Require(mips.size() == 2, "linear mip chain must contain the requested mip count"); Require(mips[0].tiledOffset == 512 && mips[0].tiledSize == 1024, "linear mip 0 offset or size changed"); Require(mips[0].width == 4 && mips[0].height == 4, "linear mip 0 dimensions changed"); Require(mips[0].blocksPerRow == 256 && mips[0].pitchBytes == 256, "linear mip 0 row layout changed"); Require(!mips[0].tail, "linear mips must never fall into a mip tail"); Require(mips[1].tiledOffset == 0 && mips[1].tiledSize == 512, "linear mip 1 offset or size changed"); Require(mips[1].width == 2 && mips[1].height == 2, "linear mip 1 dimensions changed"); Require(mips[1].linearOffset == mips[1].tiledOffset && mips[1].linearSize == mips[1].tiledSize, "linear tiling must keep linear and tiled layout identical"); } { const auto mips = ComputeMipLayout(TextureTileMode::kLinear, 169, 8, 8, 1); Require(mips.size() == 1, "compressed linear layout must contain one mip"); Require(mips[0].width == 2 && mips[0].height == 2, "compressed linear mip block dimensions changed"); Require(mips[0].blocksPerRow == 32 && mips[0].pitchBytes == 256, "compressed linear mip row layout changed"); Require(mips[0].tiledSize == 512 && mips[0].linearSize == 512, "compressed linear mip size changed"); } { const auto mips = ComputeMipLayout(TextureTileMode::kStandard256B, 1, 64, 64, 1); Require(mips.size() == 1, "standard 256B layout must contain one mip"); Require(mips[0].tiledOffset == 0 && mips[0].tiledSize == 4096, "standard 256B mip 0 offset or size changed"); Require(mips[0].width == 64 && mips[0].height == 64, "standard 256B mip 0 dimensions changed"); Require(mips[0].blocksPerRow == 4 && mips[0].pitchBytes == 64, "standard 256B mip 0 row layout changed"); Require(!mips[0].tail, "standard 256B textures must never use a mip tail"); const auto surfaceSize = ComputeSurfaceSize(mips, 3); Require(surfaceSize == 4096ull * 3ull, "surface size must multiply the slice size by the array layer count"); } { const auto mips = ComputeMipLayout(TextureTileMode::kStandard256B, 1, 32, 32, 6); Require(mips.size() == 6, "standard 256B mip chain must contain the requested mip count"); for (const auto& mip : mips) Require(!mip.tail, "standard 256B tile mode must never produce a mip tail"); } { const auto mips = ComputeMipLayout(TextureTileMode::kStandard64KB, 1, 1024, 1024, 11); Require(mips.size() == 11, "standard 64KB mip chain must contain the requested mip count"); auto tailSeen = false; for (const auto& mip : mips) { Require(mip.width != 0 && mip.height != 0, "every standard 64KB mip must have nonzero dimensions"); Require(mip.tiledSize != 0 && mip.linearSize != 0, "every standard 64KB mip must have a nonzero size"); if (mip.tail) { tailSeen = true; Require(mip.blocksPerRow == 1, "mip tail levels must report a single block per row"); Require(mip.tiledOffset == 0 && mip.linearOffset == 0, "mip tail levels must share the tail block offset"); } } Require(tailSeen, "a deep standard 64KB mip chain must fall into the mip tail"); Require(!mips.front().tail, "the base level of a deep mip chain must not be in the mip tail"); } { const auto mips = ComputeMipLayout(TextureTileMode::kStandard4KB, 1, 512, 512, 10); Require(mips.size() == 10, "standard 4KB mip chain must contain the requested mip count"); auto tailSeen = false; for (const auto& mip : mips) { if (mip.tail) tailSeen = true; } Require(tailSeen, "a deep standard 4KB mip chain must fall into the mip tail"); } reject([] { ComputeMipLayout(TextureTileMode::kLinear, 1, 0, 4, 1); }, "zero-sized texture"); reject([] { ComputeMipLayout(TextureTileMode::kLinear, 1, 4, 0, 1); }, "zero-sized texture"); reject([] { ComputeMipLayout(TextureTileMode::kLinear, 1, 4, 4, 0); }, "mip count is out of range"); reject([] { ComputeMipLayout(TextureTileMode::kLinear, 1, 4, 4, 17); }, "mip count is out of range"); reject([] { ComputeSurfaceSize({}, 1); }, "empty mip chain"); reject([] { ComputeSurfaceSize(ComputeMipLayout(TextureTileMode::kLinear, 1, 4, 4, 1), 0); }, "zero array layers"); }