fix(agc): initialize point size and limits from SDK defaults

This commit is contained in:
JJenkx committed 2026-10-19 02:48:17 -04:00
1 parent 7f596df48d
commit c8d7e37f4c
3 files changed
+10 -1

No files matched your search

@@ -228,7 +228,7 @@ inline Registers BuildInitialContextRegisters() {
{0x105, 0}, {0x106, 0}, {0x107, 0}, {0x108, 0},
{0x10b, 0}, {0x10c, 0}, {0x10d, 0},
{0x1b1, 0}, {0x1b3, 0}, {0x1b4, 0}, {0x1b6, 0}, {0x1c3, 0}, {0x1c4, 0}, {0x1c5, 0},
{0x1ff, 0}, {0x292, 2}, {0x293, 0}, {0x29b, 0},
{0x1ff, 0}, {0x280, 0x00080008}, {0x281, 0xffff0000}, {0x292, 2}, {0x293, 0}, {0x29b, 0},
{0x2ce, 0}, {0x2d3, 0}, {0x2d5, 0}, {0x2d6, 0}, {0x2db, 0},
{0x2dc, 0xaa00}, {0x2df, 0}, {0x2e4, 0}, {0x2f8, 0}, {0x2f9, 0x2d},
{0x30e, 0xffffffff}, {0x30f, 0xffffffff}, {0x313, 0x6000},
@@ -186,16 +186,22 @@ void testRegisterFile() {
void testContextAndBases() {
AgcDriver::QueueState state;
check(state.context.contains(0x280) && state.context.at(0x280) == 0x00080008u && state.context.contains(0x281) && state.context.at(0x281) == 0xffff0000u, "initial point context differs from the SDK defaults");
execute(state, makePacket(0x69, {0x280, 0x00180018u, 0x00400008u}));
check(state.context.at(0x280) == 0x00180018u && state.context.at(0x281) == 0x00400008u, "explicit point size and limits were not stored");
for (const auto offset : {0x10bu, 0x10cu, 0x10du}) execute(state, makePacket(0x69, {offset, 0xffffffffu}));
execute(state, makePacket(0x12, {0}));
for (const auto offset : {0x10bu, 0x10cu, 0x10du}) check(state.context.at(offset) == 0, "CLEAR_STATE did not restore stencil defaults");
check(state.context.at(0x280) == 0x00080008u && state.context.at(0x281) == 0xffff0000u, "CLEAR_STATE did not restore point size and limits");
execute(state, makePacket(0x69, {0x10, 17}));
execute(state, makePacket(0x76, {0x20c, 2}));
execute(state, makePacket(0x10, {3, 0}, 0x68));
check(state.context == AgcDriver::InitialContextRegisters() && state.shader.at(0x20c) == 2, "push-clear reset wrong state");
expectFailure([&] { execute(state, makePacket(0x10, {1, 0}, 0x68)); }, "already pushed");
execute(state, makePacket(0x69, {0x10, 19}));
execute(state, makePacket(0x69, {0x280, 0x00100010u, 0x00800010u}));
execute(state, makePacket(0x10, {2, 0}, 0x68));
check(state.context.at(0x280) == 0x00080008u && state.context.at(0x281) == 0xffff0000u, "context pop did not restore saved point size and limits");
check(state.context.at(0x10) == 17, "pop did not restore context");
expectFailure([&] { execute(state, makePacket(0x10, {2, 0}, 0x68)); }, "not been pushed");
alignas(8) std::array<std::uint32_t, 4> arguments{7, 8, 9, 0};
+3
View File
@@ -8,6 +8,9 @@
- [sceAgcDriverSubmitCommandBuffer, sceAgcDriverSubmitMultiCommandBuffers](../../../core/libs/prx/libSceAgcDriver/Submit/src/CommandBuffer.cpp) (libSceAgcDriver) - `queue_context` is treated as a pointer to context whose queue identifier is stored 4 bytes in, matching KytyPS5 (`src/libs/agc.cpp` `AgcDriverSubmitCommandBuffer` / `get_driver_queue`). A null context returns `EINVAL` (22). Whether the console validates other context fields before queue dispatch is unverified
- [Initial point context](../../../core/libs/prx/libSceAgcDriver/Execution/include/QueueState.hpp) - new queues and CLEAR_STATE seed PA_SU_POINT_SIZE 0x00080008 and PA_SU_POINT_MINMAX 0xffff0000, matching every public context table in libSceAgc/Command/include/RegisterDefaultsData.hpp. Cocoon (PPSA08766) reaches geometry point output without writing these registers in the observed startup. Applying the SDK context defaults to initial/CLEAR_STATE driver context is inferred; GPU power-on reset state is not measured and is not the source of these values. Explicit writes and pushed/restored contexts retain their own values.
- [Optional BMP frame dumps](../../../core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp) use checked host stdio. An open, header, pixel or close failure prints one diagnostic and disables subsequent BMP dumps for the process; queued frames drain without more file I/O. Pixel validation and allocation failures retain the existing fatal path. The CPU fixture checks identical BMP bytes and real pipe failures. VideoOut flips on an RTX 3060 continue after a first dump that cannot be opened; header, pixel and close failures during presentation are unmeasured.
- [Inactive vertex point size](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) - `PA_CL_VS_OUT_CNTL.USE_VTX_POINT_SIZE` is accepted for lines, triangles and rectangles with `GS_EN` and `HS_EN` clear, when polygon mode is disabled or both faces are filled. Points, patches and absent routing or rasterization registers still throw. Bit 16 selects the misc export's X component as PointSize ([AMD CIK register reference](https://www.amd.com/content/dam/amd/en/documents/radeon-tech-docs/programmer-references/CIK_3D_registers_v2.pdf), PA_CL_VS_OUT_CNTL); ignoring it for non-point rasterization follows [Vulkan PointSize](https://docs.vulkan.org/refpages/latest/refpages/source/PointSize.html). This is inferred, not measured on console hardware. XashPS5 (PPSA19111 v1.3) sets `0x01210000` on a filled triangle draw.