mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
feat(libSceAgc): implement sceAgcGetDefaultCxStateFlat
This commit is contained in:
1 parent
4186f06a9a
commit
fd90df41b6
7 files changed
+65
-7
No files matched your search
@@ -6,6 +6,7 @@
|
||||
namespace Agc::Command {
|
||||
|
||||
void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* function);
|
||||
int GetDefaultCxStateFlat(void* destination, std::uint32_t size);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
@@ -44,6 +45,33 @@ struct Storage {
|
||||
std::mutex defaultsMutex;
|
||||
std::array<std::array<Storage, 14>, 2> storage;
|
||||
|
||||
struct AgcContextState {
|
||||
std::uint32_t data[512];
|
||||
};
|
||||
|
||||
static_assert(sizeof(AgcContextState) == 2048);
|
||||
|
||||
std::mutex defaultStateMutex;
|
||||
AgcContextState defaultState{};
|
||||
bool defaultStateInitialized = false;
|
||||
|
||||
void InitDefaultCxState() {
|
||||
std::memset(&defaultState, 0, sizeof(defaultState));
|
||||
const auto* source = agcPublicRegDefaultsByVersion[8];
|
||||
for (std::size_t bank = 0; bank < 4; ++bank) {
|
||||
const auto& b = source->banks[bank];
|
||||
if (b.registers == nullptr) continue;
|
||||
for (std::uint32_t r = 0; r < b.registerCount; ++r) {
|
||||
const auto offset = b.registers[r].offset;
|
||||
const auto value = b.registers[r].value;
|
||||
if (offset < 512) {
|
||||
defaultState.data[offset] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
defaultStateInitialized = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* function) {
|
||||
@@ -76,4 +104,15 @@ void* GetRegisterDefaults(std::uint32_t version, bool internal, const char* func
|
||||
return &destination.defaults;
|
||||
}
|
||||
|
||||
int GetDefaultCxStateFlat(void* destination, std::uint32_t size) {
|
||||
if (destination == nullptr) return static_cast<int>(0x80890001);
|
||||
std::lock_guard lock(defaultStateMutex);
|
||||
if (!defaultStateInitialized) {
|
||||
InitDefaultCxState();
|
||||
}
|
||||
const auto copyBytes = std::min(size, static_cast<std::uint32_t>(sizeof(AgcContextState)));
|
||||
std::memcpy(destination, defaultState.data, copyBytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
#ifndef CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_REGISTERDEFAULTS_HPP
|
||||
#define CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_REGISTERDEFAULTS_HPP
|
||||
#include "SceTypes.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI sceAgcGetDefaultCxStateFlat(void* out_state, std::uint32_t size);
|
||||
}
|
||||
#endif
|
||||
@@ -26,4 +26,8 @@ void* APS5_VABI sceAgcGetRegisterDefaults2Internal(std::uint32_t version) {
|
||||
return Agc::Command::GetRegisterDefaults(version, true, __func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcGetDefaultCxStateFlat(void* out_state, std::uint32_t size) {
|
||||
return Agc::Command::GetDefaultCxStateFlat(out_state, size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,11 +30,6 @@ int APS5_VABI sceAgcDcbSetMarkerSpan() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcGetDefaultCxStateFlat() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcSetSemaphoreMemory() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
|
||||
@@ -21,6 +21,7 @@ extern "C" int APS5_VABI sceAgcInit(std::uint32_t version);
|
||||
extern "C" void* APS5_VABI sceAgcGetRegisterDefaults();
|
||||
extern "C" void* APS5_VABI sceAgcGetRegisterDefaultsInternal();
|
||||
extern "C" void* APS5_VABI sceAgcGetRegisterDefaults2Internal(std::uint32_t version);
|
||||
extern "C" int APS5_VABI sceAgcGetDefaultCxStateFlat(void* out_state, std::uint32_t size);
|
||||
extern "C" int APS5_VABI sceAgcInit_0090(std::uint32_t* state, std::uint32_t version);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexAuto(CommandBuffer* buf, std::uint32_t indexCount, std::uint64_t modifier);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirect(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint64_t modifier);
|
||||
@@ -637,8 +638,20 @@ void testDefaults() {
|
||||
auto* internalDefaults = sceAgcGetRegisterDefaultsInternal();
|
||||
check(internalDefaults != nullptr && internalDefaults == Agc::Command::GetRegisterDefaults(0, true, __func__) && internalDefaults == sceAgcGetRegisterDefaults2Internal(0), "internal register defaults are not the baseline internal table");
|
||||
check(internalDefaults != sceAgcGetRegisterDefaults(), "internal register defaults returned the public table");
|
||||
expectFailure([] { Agc::Command::GetRegisterDefaults(14, false, __func__); });
|
||||
expectFailure([] { Agc::Command::GetRegisterDefaults(0xffffffffu, true, __func__); });
|
||||
std::array<std::uint32_t, 512> flatCxBuffer{};
|
||||
check(sceAgcGetDefaultCxStateFlat(nullptr, sizeof(flatCxBuffer)) == SCE_AGC_ERROR_INVALID_ARGUMENT, "null destination was accepted");
|
||||
check(sceAgcGetDefaultCxStateFlat(flatCxBuffer.data(), 0) == 0, "zero size copy failed");
|
||||
check(sceAgcGetDefaultCxStateFlat(flatCxBuffer.data(), sizeof(flatCxBuffer)) == 0, "flat CX state default retrieval failed");
|
||||
check(flatCxBuffer[0x001] == 0x11000100u, "flat CX state register 0x001 mismatch");
|
||||
check(flatCxBuffer[0x007] == 0x0000ffffu, "flat CX state register 0x007 mismatch");
|
||||
check(flatCxBuffer[0x12d] == 0x3f800000u, "flat CX state register 0x12d mismatch");
|
||||
check(flatCxBuffer[0x1e0] == 0x20010001u, "flat CX state register 0x1e0 mismatch");
|
||||
std::array<std::uint32_t, 513> overBuffer{};
|
||||
overBuffer[512] = 0x12345678u;
|
||||
check(sceAgcGetDefaultCxStateFlat(overBuffer.data(), sizeof(overBuffer)) == 0, "oversized copy failed");
|
||||
check(overBuffer[512] == 0x12345678u, "oversized copy overflowed buffer");
|
||||
check(Agc::Command::GetDefaultCxStateFlat(nullptr, sizeof(flatCxBuffer)) == SCE_AGC_ERROR_INVALID_ARGUMENT, "null command destination was accepted");
|
||||
check(Agc::Command::GetDefaultCxStateFlat(flatCxBuffer.data(), sizeof(flatCxBuffer)) == 0, "command flat CX state retrieval failed");
|
||||
}
|
||||
|
||||
void testEventWrite() {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
- [sceAgcDcbSetZPassPredicationEnableGetSize, sceAgcDcbSetPredicationDisableGetSize, sceAgcDcbSetBoolPredicationEnableGetSize](../../../core/libs/prx/libSceAgc/DcbState/src/Predication.cpp) (libSceAgc) - the builders are inline in the SDK and not exported; the size is assumed to be that of the SET_PREDICATION packet `sceAgcDcbSetPredication` writes (16 bytes)
|
||||
- [vieBRwlh1Lw](../../../core/libs/prx/libSceAgc/Shader/src/InterpolantMapping.cpp) (libSceAgc) follows [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c) only, not confirmed on hardware: the `dbOlWdppb4o` transform without the identity tail, so it writes one register per pixel shader input and none for a pixel shader without inputs, and a null pixel shader throws. For an `is_f16` 1 or 3 input whose `default_value` and `default_value_hi` differ it throws: OpenAGC takes `DEFAULT_VAL` from `default_value_hi`, while KytyPS5, sharpemu and `dbOlWdppb4o` here take it from `default_value`
|
||||
- [sceAgcAcbWaitUntilSafeForRendering](../../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - `(buffer, videoOutHandle, displayBufferIndex)`, the declared arguments, which PPSA12544 (01.000.010) passes inside `waitUntilSafeForRendering` and `waitUntilSafeForRendering VR` markers on an asynchronous compute command buffer, ignoring the result. It writes the same rendering-wait packet as `sceAgcDcbWaitUntilSafeForRendering`, which the driver now accepts on compute queues too; the wait blocks only that queue's worker. Whether the console encodes the compute variant differently is not known
|
||||
- [sceAgcGetDefaultCxStateFlat](../../../core/libs/prx/libSceAgc/Misc/src/RegisterDefaults.cpp) (libSceAgc) - copies up to `size` bytes (clamped to 2048 bytes, the 512-dword `AgcContextState`) from the default context state initialized from the version 8 public register default groups (CX, SH, UC), indexed by register offset, following OpenAGC `src/context_state.c`; returns `0x80890001` on null destination; version selection without `sceAgcInit` is unverified
|
||||
|
||||
### Functional
|
||||
|
||||
|
||||
Reference in new issue
Block a user