Repository navigation
Minecraft Preview (PPSA19639) #1277
ddrsilva
started this conversation in
Game bring-up
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Minecraft Preview (PPSA19639)
Tested
mainatd4c196c2plus a local patch (below), WinLibs MinGW-w64 GCC 15.2, Ninja, ReleaseStatus
gfx_viewdistance:576), the game issues 2,000–4,000 draws per frame.main: about 7 fps, because the queue worker spends 76–80 µs of CPU per draw.Stops on
main, in the order they are hitEach one is fixed or worked around in my patch. Some are stubs and not ready to merge as they are.
sceHttp2SendRequestAsyncmust return 0 (the failure belongs atWaitAsync). With a synchronousERROR_NETWORK, the game throwsbad_weak_ptron its "REST Thread".sceNetCtlCheckCallback. NpManager must register the state callbacks and deliver SIGNED_OUT once fromsceNpCheckCallback.sceSaveDataDirNameSearchwith atitle_idother than the running title (the game searches PPSA17221) must return 0 hits.sync()aborts. libkernelsync()throws on volumes that are not ready or not accessible (it needs admin otherwise). It should skip them.sockaddrparsing must ignoresa_len, as BSD does. RakNet leaves it at 0, everybindfailed, and the RakNet server locator crashed on a null peer.setsockoptmust also accept the BSD options Winsock lacks, plusSO_NBIO(0x1200).libSceTextToSpeech2andlibSceNpAuthAuthorizedAppDialog. Stub thesceKernelAdd/DeleteRead/WriteEventandWriteThrottlingStatusexports.pthread_attr_setstacksizebelow 16 KiB must return EINVAL.sceNpAuthCreateRequest/GetIdTokenV3/WaitAsyncwere NotImplemented. They now return signed-out like their siblings.sceImeOpennow returns an error instead of throwing.sceSaveDataMount3with an invalid directory name now returnsSAVE_DATA_ERROR_PARAMETERinstead of aborting.EVENT_WRITEtype 1 with 2 dwords (stream-out stats, no address) is accepted as a no-op. Before, it was an intermittent abort on the GPU thread.sceSaveDataDirNameSearch(key = BLOCKS)and sumsinfos[i].blocksover all saves against a budget.mainnever filledinfos, andgetMountInforeported 32,768 blocks for every save.SaveDataSearchInforecords and remembers the allocation frommount3. It reports used blocks as the sum of file sizes in 32 KiB blocks.sceKernelFsyncon directories. It must return 0; LevelDB fsyncs directories.The performance work (the improvement I'd most like upstream)
At 36 chunks the bottleneck is the single queue-0 worker thread. The GPU is mostly idle. Chunk draws are thousands of nearly identical draws: between draws, only a few shader user-data words change (registers 0x24, 0x8c, 0x90, 0x92, pointers into a per-draw constant ring) plus the index range.
Single-thread work: 76–80 µs down to ~36 µs per draw
operator new/deletewent through a locked heap at 80–100 ns per call, a few hundred times per draw. The operators must be excluded from the DLL exports, orlibSceAgc.prxfails to load (error 127).Parallel draw preparation ("draw runs"): 7 fps up to 31 fps
What made the helpers scale, measured on the scene above:
BuffereachvkFree+vkAllocateunder one mutexoperator newwas 21% of helper timePendingStorageOverlapsandAnyShadowedOverlapsFinal per-draw cost: helpers ~17–21 µs per job, worker ~2.5–3.3 µs per commit, ~8 µs wall time per draw.
A trap I hit: the result memo must not be bypassed on the worker or other threads. Later caches recognise a result by the identity of the memo's shared object, and with a fresh object every call, world loading crawled at 3–4 fps.
Open problems on
main(not fixed in the patch)GuestAllocations) stalls the GPU thread and the game. This is the most important one for normal play, because moving around streams chunks constantly.GuestAllocationsAcquirecopies theshared_ptrof every range (4,000–5,000 here) under the registry mutex, and pins every range until the lease is dropped.DoMapDirectheld it for up to 50–60 ms at a time, and the registry was locked about 9 s out of every 10 s.GuestAllocationsAcquirefor the whole time), and the game's ownsceKernelVirtualQuerycalls waiting about 31 ms each.sceKernelVirtualQuerybuilds a full lease for every call and then scans it linearly. A locked lookup by address would do.minImageCount(2 on NVIDIA) in FIFO mode is double-buffered vsync. The patch usesminImageCount + 1(APS5_SWAPCHAIN_IMAGES, plus an opt-inAPS5_PRESENT_MODE).Notes
APS5_NO_WORKER_ALLOCATOR,APS5_NO_DIRECT_DRAW_INPUTS,APS5_NO_DECODE_MEMO,APS5_NO_DRAW_REPEAT,APS5_DRAW_HELPERS=0,APS5_NO_SNAPSHOT_ARENA,APS5_NO_DESCRIPTOR_RECYCLEandAPS5_NO_MEMO_BYPASS.APS5_PERF=1prints draws per frame, fps, the worker's CPU share and per-draw cost every 10 s.d4c196c2, about 57 files. I can split it into PRs (network/savedata stubs, the EOP interrupt, the single-thread work, the parallel draw runs) if that helps.Stack tried
mainatd4c196c2plus the local patch. No other branches.Patch (applies to
d4c196c2withgit apply): minecraft-overlay-latest.patchAll reactions