AnyPS5/core/libs/prx/libSceAgcDriver/tests/DccKeySharing.cpp

151 lines
5.7 KiB
C++

#include "prx/libSceAgcDriver/Graphics/include/DccMetadata.hpp"
#include <cstdint>
#include <cstdio>
#include <map>
#include <optional>
using namespace AgcDriver::Graphics;
namespace {
int failures = 0;
void Expect(bool condition, const char* what) {
if (condition) return;
std::fprintf(stderr, "FAIL: %s\n", what);
++failures;
}
struct Keys {
std::map<std::uint64_t, DccKeys> ranges;
int reads = 0;
DccKeys Read(std::uint64_t address) {
++reads;
if (address == 0) return DccKeys::Uncompressed;
const auto it = ranges.find(address);
return it == ranges.end() ? DccKeys::Uncompressed : it->second;
}
};
struct Image {
std::uint64_t dcc = 0;
DccKeys uploaded = DccKeys::Uncompressed;
DccKeys filled = DccKeys::Uncompressed;
};
struct SurfaceCache {
Keys& keys;
bool shared = true;
std::optional<Image> image;
int made = 0;
int remade = 0;
int uploads = 0;
bool Serves(const Image& held, std::uint64_t named) {
if (!shared) return named == 0 || named == held.dcc;
return KeysServeSurface(held.dcc, held.uploaded, held.filled, named, [&] { return keys.Read(held.dcc); }, [&] { return keys.Read(named); });
}
const Image& Lookup(std::uint64_t named) {
if (image.has_value() && Serves(*image, named)) {
const auto current = keys.Read(image->dcc);
if (current != image->uploaded) {
image->uploaded = current;
++uploads;
}
return *image;
}
if (image.has_value()) ++remade;
else ++made;
image = Image{named, keys.Read(named), DccKeys::Uncompressed};
++uploads;
return *image;
}
};
constexpr std::uint64_t TargetKeys = 0x570526000;
constexpr std::uint64_t StorageKeys = 0x5705e0000;
void worldMapFrames() {
for (const bool shared : {true, false}) {
Keys keys;
SurfaceCache cache{keys, shared};
for (int frame = 0; frame < 100; ++frame) {
cache.Lookup(TargetKeys);
cache.Lookup(StorageKeys);
cache.Lookup(StorageKeys);
}
if (shared) {
Expect(cache.made == 1 && cache.remade == 0, "a surface whose two descriptors name uncompressed keys was remade");
Expect(cache.uploads == 1, "a shared surface was uploaded again with nothing changed");
Expect(cache.image->dcc == TargetKeys, "the shared image left the keys it follows");
} else {
Expect(cache.remade == 199, "the unshared model does not reproduce the map's two remakes a frame");
}
}
}
void namedClearRemakes() {
Keys keys;
SurfaceCache cache{keys};
cache.Lookup(TargetKeys);
keys.ranges[StorageKeys] = DccKeys::Clear0000;
const auto& image = cache.Lookup(StorageKeys);
Expect(cache.remade == 1 && image.dcc == StorageKeys && image.uploaded == DccKeys::Clear0000, "a fast clear of the named keys did not reach the surface's image");
const auto& own = cache.Lookup(StorageKeys);
Expect(cache.remade == 1 && own.uploaded == DccKeys::Clear0000, "the image of the cleared keys did not serve its own keys");
cache.Lookup(TargetKeys);
Expect(cache.remade == 2, "uncompressed keys shared an image holding a clear");
}
void followedClearRemakes() {
Keys keys;
SurfaceCache cache{keys};
cache.Lookup(TargetKeys);
keys.ranges[TargetKeys] = DccKeys::Clear1111;
const auto& image = cache.Lookup(StorageKeys);
Expect(cache.remade == 1 && image.dcc == StorageKeys && image.uploaded == DccKeys::Uncompressed, "a descriptor over uncompressed keys was served an image whose own keys are a clear");
}
void filledKeysRemake() {
Keys keys;
SurfaceCache cache{keys};
cache.Lookup(TargetKeys);
cache.image->filled = DccKeys::Clear0001;
cache.Lookup(StorageKeys);
Expect(cache.remade == 1, "an image holding a key fill served other keys");
}
void serveRules() {
Keys keys;
keys.ranges[TargetKeys] = DccKeys::Clear0000;
Expect(KeysServeSurface(TargetKeys, DccKeys::Clear0000, DccKeys::Uncompressed, 0, [&] { return keys.Read(TargetKeys); }, [&] { return keys.Read(0); }), "a descriptor without metadata was refused");
Expect(KeysServeSurface(TargetKeys, DccKeys::Clear0000, DccKeys::Uncompressed, TargetKeys, [&] { return keys.Read(TargetKeys); }, [&] { return keys.Read(TargetKeys); }), "the image's own keys were refused");
Expect(keys.reads == 0, "the own-keys and no-metadata answers scanned keys");
Expect(!KeysServeSurface(TargetKeys, DccKeys::Clear0000, DccKeys::Uncompressed, StorageKeys, [&] { return keys.Read(TargetKeys); }, [&] { return keys.Read(StorageKeys); }), "an image uploaded under a clear served other keys");
Expect(keys.reads == 0, "a refusal by the uploaded keys scanned keys");
keys.ranges[StorageKeys] = DccKeys::Mixed;
keys.ranges[TargetKeys] = DccKeys::Uncompressed;
Expect(!KeysServeSurface(TargetKeys, DccKeys::Uncompressed, DccKeys::Uncompressed, StorageKeys, [&] { return keys.Read(TargetKeys); }, [&] { return keys.Read(StorageKeys); }), "keys that do not read uncompressed were served");
int followedReads = 0;
Expect(KeysServeSurface(0, DccKeys::Uncompressed, DccKeys::Uncompressed, TargetKeys, [&] { ++followedReads; return DccKeys::Clear0000; }, [&] { return keys.Read(TargetKeys); }), "an image without metadata did not serve uncompressed keys");
Expect(followedReads == 0, "an image without metadata scanned keys of its own");
}
}
int main() {
worldMapFrames();
namedClearRemakes();
followedClearRemakes();
filledKeysRemake();
serveRules();
if (failures != 0) {
std::fprintf(stderr, "%d DCC key sharing checks failed\n", failures);
return 1;
}
std::printf("DCC key sharing tests passed\n");
return 0;
}