Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion core/libs/prx/libSceAgc/Command/include/RegisterDefaults.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@

namespace Agc::Command {

void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* function);
enum class RegisterDefaultsTypeLayout {
Compact,
KeyBankPairs,
};

void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* function,
RegisterDefaultsTypeLayout typeLayout = RegisterDefaultsTypeLayout::Compact);
int GetDefaultCxStateFlat(void* destination, std::uint32_t size);

}
Expand Down
28 changes: 18 additions & 10 deletions core/libs/prx/libSceAgc/Command/src/RegisterDefaults.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static_assert(sizeof(TypeIndex) == 8);
struct RegisterDefaults {
ShaderRegister** tables[4];
std::uint32_t registerCounts[4];
TypeIndex* types;
void* types;
std::uint32_t count;
};

Expand Down Expand Up @@ -52,7 +52,7 @@ struct Storage {
};

std::mutex defaultsMutex;
std::array<std::array<Storage, 14>, 2> storage;
std::array<std::array<std::array<Storage, 14>, 2>, 2> storage;

struct AgcContextState {
std::uint32_t data[512];
Expand Down Expand Up @@ -83,11 +83,13 @@ void InitDefaultCxState() {

}

void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* function) {
void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* function,
RegisterDefaultsTypeLayout typeLayout) {
Require(version < 14, function, "unsupported register defaults version");
const auto* source = internal ? agcInternalRegDefaultsByVersion[version] : agcPublicRegDefaultsByVersion[version];
std::lock_guard lock(defaultsMutex);
auto& destination = storage[internal ? 1 : 0][version];
const auto layoutIndex = typeLayout == RegisterDefaultsTypeLayout::KeyBankPairs ? 1 : 0;
auto& destination = storage[internal ? 1 : 0][layoutIndex][version];
if (!destination.initialized) {
std::array<std::vector<ShaderRegister*>, 4> pointers;
RegisterDefaults defaults{};
Expand All @@ -105,13 +107,19 @@ void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* func
}
Require(source->count == 0 || source->types != nullptr, function, "missing register defaults types");
std::vector<TypeIndex> types;
types.reserve(source->count);
for (std::uint32_t entry = 0; entry < source->count; ++entry) {
const std::uint32_t bankIndex = source->types[entry * 3 + 1] & 0x3ffu;
Require((bankIndex >> 2) < source->banks[bankIndex & 3u].pointerCount, function, "register defaults type exceeds its bank");
types.push_back({source->types[entry * 3], bankIndex});
if (typeLayout == RegisterDefaultsTypeLayout::KeyBankPairs) {
types.reserve(source->count);
for (std::uint32_t entry = 0; entry < source->count; ++entry) {
const std::uint32_t bankIndex = source->types[entry * 3 + 1] & 0x3ffu;
Require((bankIndex >> 2) < source->banks[bankIndex & 3u].pointerCount, function, "register defaults type exceeds its bank");
types.push_back({source->types[entry * 3], bankIndex});
}
}
if (typeLayout == RegisterDefaultsTypeLayout::KeyBankPairs) {
defaults.types = types.empty() ? nullptr : types.data();
} else {
defaults.types = source->types;
}
defaults.types = types.empty() ? nullptr : types.data();
defaults.count = source->count;
destination.pointers = std::move(pointers);
destination.types = std::move(types);
Expand Down
2 changes: 1 addition & 1 deletion core/libs/prx/libSceAgc/Misc/src/RegisterDefaults.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
extern "C" {

void* APS5_VABI sceAgcGetRegisterDefaults() {
return Agc::Command::GetRegisterDefaults(13, false, __func__);
return Agc::Command::GetRegisterDefaults(13, false, __func__, Agc::Command::RegisterDefaultsTypeLayout::KeyBankPairs);
}

void* APS5_VABI sceAgcGetRegisterDefaultsInternal() {
Expand Down
23 changes: 18 additions & 5 deletions core/libs/prx/libSceAgc/tests/Commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -692,11 +692,24 @@ std::uint32_t colourTargetBlock(const void* root) {
}

void testDefaultsTypes() {
check(sceAgcGetRegisterDefaults() == sceAgcGetRegisterDefaults2(13), "legacy register defaults are not the newest public table");
check(colourTargetBlock(sceAgcGetRegisterDefaults()) == 78, "MRT0 defaults are not block 78 of the 137-entry table");
check(colourTargetBlock(sceAgcGetRegisterDefaults2(10)) == 73, "MRT0 defaults are not block 73 of the 128-entry table");
for (std::uint32_t version = 4; version < 14; ++version)
colourTargetBlock(sceAgcGetRegisterDefaults2(version));
const auto* legacy = sceAgcGetRegisterDefaults();
check(legacy != sceAgcGetRegisterDefaults2(13), "legacy register defaults reused the compact versioned table");
check(colourTargetBlock(legacy) == 78, "MRT0 defaults are not block 78 of the 137-entry table");

const auto checkCompactTypes = [](const void* root, std::uint32_t count, std::uint32_t key,
std::uint32_t packedType, std::uint32_t extra) {
const auto* bytes = static_cast<const unsigned char*>(root);
const std::uint32_t* types = nullptr;
std::uint32_t actualCount = 0;
std::memcpy(&types, bytes + 0x30, sizeof(types));
std::memcpy(&actualCount, bytes + 0x38, sizeof(actualCount));
check(types != nullptr && actualCount == count, "versioned register defaults have an invalid compact type table");
check(types[0] == key && types[1] == packedType && types[2] == extra,
"versioned register defaults did not preserve their compact type entry");
};
checkCompactTypes(sceAgcGetRegisterDefaults2(0), 150, 0xe24f806du, 0x00040400u, 0);
checkCompactTypes(sceAgcGetRegisterDefaults2(10), 128, 0xe24f806du, 0x00040400u, 0);
checkCompactTypes(sceAgcGetRegisterDefaults2Internal(0), 15, 0xf58fea31u, 0x00040400u, 0);
}

void testEventWrite() {
Expand Down
4 changes: 3 additions & 1 deletion core/libs/tests/GuestShaderLink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ int main() {
using namespace ShaderRegs;
auto* defaults = static_cast<unsigned char*>(sceAgcGetRegisterDefaults());
Require(defaults && defaults == sceAgcGetRegisterDefaults());
Require(defaults == sceAgcGetRegisterDefaults2(13));
auto* versionedDefaults = static_cast<unsigned char*>(sceAgcGetRegisterDefaults2(13));
Require(versionedDefaults != nullptr);
Require(std::memcmp(defaults + 0x20, versionedDefaults + 0x20, 4 * sizeof(std::uint32_t)) == 0);
// These are the byte offsets used by native callers, independent of the
// private C++ structure used to construct the defaults object.
ShaderRegister** contextBlocks = nullptr;
Expand Down
Loading