Skip to content

feat(libSceGLSlimVSH): implement EGL 1.4 and GLES 2.0 state, objects and pbuffer storage - #13868

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
PrivacyOnion:feat/glslimvsh
Nov 1, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
PrivacyOnion:feat/glslimvsh

Conversation

@PrivacyOnion

@PrivacyOnion PrivacyOnion commented Oct 31, 2026 •

Copy link
Copy Markdown

What

Implements libSceGLSlimVSH EGL 1.4 and OpenGL ES 2.0 as a host-side state machine following the Khronos specifications (EGL 1.4, OpenGL ES 2.0.25). 138 of the library's 210 exports no longer throw; 72 stay NotImplemented_nid_no_patch.

  • EGL: default display, one RGBA8/depth16/stencil8 pbuffer configuration (eglChooseConfig matching, eglGetConfigAttrib), ES2 contexts with share groups, pbuffer surfaces with CPU color/depth/stencil storage, per-thread current context and eglGetError, eglMakeCurrent/eglReleaseThread/eglTerminate lifetime rules, surface and context queries, eglGetProcAddress.
  • GLES2: buffers, textures (2D and cube, GL_RGB/GL_RGBA/GL_ALPHA/GL_LUMINANCE/GL_LUMINANCE_ALPHA with byte and packed 565/4444/5551 types, unpack alignment, glGenerateMipmap), renderbuffers, framebuffers and completeness, shader and program objects and attachment rules, vertex attributes, every fixed-function setter and glGet* query with its default, the error flag, and glClear (scissor, masks), glReadPixels, glTexSubImage2D, glCopyTexImage2D/glCopyTexSubImage2D on that storage.
  • The 22 unknown NIDs are named from the NID database (tools/nid_names.py); each name hashes to its original NID. Exports of the 3.20 catalogue that were missing from the module are declared, so the export list matches the catalogue plus the seven unidentified NIDs.

Shader compilation, program linking and reflection, uniforms, draws, native window surfaces, client-buffer pbuffers and the Sony-specific Piglet, Orbis texture and compositor exports stay NotImplemented_nid_no_patch; no shader or program can report a successful compile or link. glGet* throws for GL_SHADER_COMPILER. These gaps and the implementation limits are in docs/dev/debt/libSceGLSlimVSH.md.

tools/pr_overlap.py reports the same export names in #6521; that PR implements them in libScePigletv2VSH, a separate module, and touches no libSceGLSlimVSH file.

Tested

Windows 11. tests/State.cpp (registered as guest_glslim_state) uses only the exported EGL/GLES entry points, so it links against the shared library without reaching its internal thread-local state. Built as a host-ABI DLL plus a test executable linked against it with MinGW GCC 13.1 and run: passes. It covers EGL config matching, context/surface lifetime across threads, error codes, state defaults and setters, object lifetime and sharing, framebuffer completeness, clears with scissor and masks, texture pixel round trips (byte RGB and packed 565) read back through a framebuffer, mipmap generation, glReadPixels with negative origins (pixel offsets are computed in size_t over the intersecting range only), and eglCreateContext rejecting the default ES1 request with EGL_BAD_CONFIG. The installed GCC 13.1 cannot build the guest runtime (it needs WinLibs 15.2 or MSYS2), so the guest build and CTest run are left to CI. python3 tools/check_conventions.py --base upstream/main and python3 core/libs/tests/test_public_headers.py --audit-only pass. The library imports only libc symbols, so no cross-library NID import is involved. Not tested with a title.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests run and reviewed — approval deferred

The source review found no substantiated blocker, but the Windows and library-portability jobs are still pending and I did not independently run the C++ test binary.

What I ran

Reviewed head 7c21f2a91eed4f72537466a931fee7951b22553e against base 02c8efdbcba38f173309ca733bc88bcb473b1f1f; the merge preview was clean against current main at cf5a1805e50ceeccf6574abd98b13e9783c412c. Environment: Linux x86_64, Python 3.11.2, GCC 12.2.0. No build or compilation was run.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13868
python3 tools/pr_abi_audit.py --base 02c8efdbcba38f173309ca733bc88bcb473b1f1f --head 7c21f2a91eed4f72537466a931fee7951b22553e --json
gh pr checks 13868 --repo boykopovar/AnyPS5

Results

Check Result
Diff whitespace Passed
Conventions and PR template Passed
Dependency and merge preview Passed; clean against current main
ABI audit Passed with warnings: 232 symbols inspected; 22 removed-placeholder-name warnings correspond to names the PR documents as recovered/renamed. This lexical audit does not verify runtime ABI.
Other precheck helpers ABI and test-quality helper copies were absent from the exact-head checkout, so the precheck could not execute those copies; I ran the ABI helper available in the workspace against the exact base/head commits.
Exact-head C++ tests Not run locally; they require a build.
Hosted intake, eligibility, report Passed
Hosted Windows and library-portability Pending at the latest check snapshot
Hosted Linux, relinker, ASAN and related jobs Skipped by workflow
Unedited local check output
# git diff --check

# conventions_and_pr_template stdout
All conventions checks passed.

# pr_stack_check summary
Target branch tip: cf5a1805e50ceeccf6574abd98b13e9783c412c1
All heads unchanged: True
PR #13868: clean against current base

Negative control

Not run: the added C++ test requires an exact-head binary, and the no-build precheck does not build one.

Findings

Blocking

None identified in the source review.

Non-blocking

The PR explicitly documents the non-conformant, single-pbuffer scope and the unimplemented shader compilation/linking, uniforms and draw/rasterization paths. I read these as declared limitations, not as claims of a complete GLES2 renderer.

Not verified

I did not build the library or run guest_glslim_state; the PR description reports that its host-ABI MinGW test passed, but I did not independently reproduce it. Console behavior is unmeasured. The Windows and library-portability CI jobs had not completed at the final snapshot.

@THEMANnt THEMANnt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 7c21f2a91eed4f72537466a931fee7951b22553e against 02c8efdbcba38f173309ca733bc88bcb473b1f1f. Request changes for the Windows test link failure below.

[P1] Avoid accessing DLL thread-local storage directly from the test. tests/State.cpp:112-113 (also 124-125) reads Slim::thread, declared as extern thread_local in the library. The added CMake target links the test against the shared libSceGLSlimVSH, rather than compiling its implementation into the executable. In an isolated Release build with MSYS2 UCRT64 GCC 16.2.0 Rev4 and the unmodified PR library CMake file, the DLL builds but guest_glslim_state_tests fails to link with undefined reference to Slim::thread and IMAGE_REL_AMD64_SECREL relocation errors. Please inspect the current surface through a function in the DLL, or keep these internal-storage assertions in a source-linked test; then build and run the registered shared-library target on Windows.

Validation: The original fixture passes when source-linked. A diagnostic copy replacing only Slim::thread.draw->image with *Slim::Color_nid_no_patch(Slim::Current_nid_no_patch(), false) links against the same DLL and passes. An independent public-API executable also passes 14 checks covering distinct read/draw surfaces, pack alignment, buffer-offset overflow, complete/mismatched cube mipmaps and deferred context deletion. The unchanged registered target still fails to link. Whitespace passes. These isolated builds use the pinned headers, guest System V ABI and a minimal throwing NotImplemented_nid_no_patch support function, rather than the full libc/game runtime. No full application, Vulkan, console or game test is claimed. Hosted Build is still in progress; Emscripten portability passes.

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Progress report (b415263 → 19af8ed)

📈 System libraries: 26.21% (+0.36%, +138 implemented, +35 declared, -22 removed functions)

✅ 138 implemented
Library Name
libSceGLSlimVSH eglBindAPI_nid_postfix
libSceGLSlimVSH eglBindTexImage_nid_postfix
libSceGLSlimVSH eglChooseConfig_nid_postfix
libSceGLSlimVSH eglCreateContext_nid_postfix
libSceGLSlimVSH eglCreatePbufferSurface_nid_postfix
libSceGLSlimVSH eglDestroyContext_nid_postfix
libSceGLSlimVSH eglDestroySurface_nid_postfix
libSceGLSlimVSH eglGetConfigAttrib_nid_postfix
libSceGLSlimVSH eglGetConfigs_nid_postfix
libSceGLSlimVSH eglGetCurrentContext_nid_postfix
libSceGLSlimVSH eglGetCurrentDisplay_nid_postfix
libSceGLSlimVSH eglGetCurrentSurface_nid_postfix
libSceGLSlimVSH eglGetDisplay_nid_postfix
libSceGLSlimVSH eglGetError_nid_postfix
libSceGLSlimVSH eglGetProcAddress_nid_postfix
libSceGLSlimVSH eglInitialize_nid_postfix
libSceGLSlimVSH eglMakeCurrent_nid_postfix
libSceGLSlimVSH eglQueryAPI_nid_postfix
libSceGLSlimVSH eglQueryContext_nid_postfix
libSceGLSlimVSH eglQueryString_nid_postfix
libSceGLSlimVSH eglQuerySurface_nid_postfix
libSceGLSlimVSH eglReleaseTexImage_nid_postfix
libSceGLSlimVSH eglReleaseThread_nid_postfix
libSceGLSlimVSH eglSurfaceAttrib_nid_postfix
libSceGLSlimVSH eglSwapBuffers_nid_postfix
libSceGLSlimVSH eglSwapInterval_nid_postfix
libSceGLSlimVSH eglTerminate_nid_postfix
libSceGLSlimVSH eglWaitClient_nid_postfix
libSceGLSlimVSH eglWaitGL_nid_postfix
libSceGLSlimVSH eglWaitNative_nid_postfix
libSceGLSlimVSH glActiveTexture_nid_postfix
libSceGLSlimVSH glAttachShader_nid_postfix
libSceGLSlimVSH glBindAttribLocation_nid_postfix
libSceGLSlimVSH glBindBuffer_nid_postfix
libSceGLSlimVSH glBindFramebuffer_nid_postfix
libSceGLSlimVSH glBindRenderbuffer_nid_postfix
libSceGLSlimVSH glBindTexture_nid_postfix
libSceGLSlimVSH glBlendColor_nid_postfix
libSceGLSlimVSH glBlendEquationSeparate_nid_postfix
libSceGLSlimVSH glBlendEquation_nid_postfix
libSceGLSlimVSH glBlendFuncSeparate_nid_postfix
libSceGLSlimVSH glBlendFunc_nid_postfix
libSceGLSlimVSH glBufferData_nid_postfix
libSceGLSlimVSH glBufferSubData_nid_postfix
libSceGLSlimVSH glCheckFramebufferStatus_nid_postfix
libSceGLSlimVSH glClearColor_nid_postfix
libSceGLSlimVSH glClearDepthf_nid_postfix
libSceGLSlimVSH glClearStencil_nid_postfix
libSceGLSlimVSH glClear_nid_postfix
libSceGLSlimVSH glColorMask_nid_postfix
libSceGLSlimVSH glCompressedTexImage2D_nid_postfix
libSceGLSlimVSH glCompressedTexSubImage2D_nid_postfix
libSceGLSlimVSH glCopyTexImage2D_nid_postfix
libSceGLSlimVSH glCopyTexSubImage2D_nid_postfix
libSceGLSlimVSH glCreateProgram_nid_postfix
libSceGLSlimVSH glCreateShader_nid_postfix
libSceGLSlimVSH glCullFace_nid_postfix
libSceGLSlimVSH glDeleteBuffers_nid_postfix
libSceGLSlimVSH glDeleteFramebuffers_nid_postfix
libSceGLSlimVSH glDeleteProgram_nid_postfix
libSceGLSlimVSH glDeleteRenderbuffers_nid_postfix
libSceGLSlimVSH glDeleteShader_nid_postfix
libSceGLSlimVSH glDeleteTextures_nid_postfix
libSceGLSlimVSH glDepthFunc_nid_postfix
libSceGLSlimVSH glDepthMask_nid_postfix
libSceGLSlimVSH glDepthRangef_nid_postfix
libSceGLSlimVSH glDetachShader_nid_postfix
libSceGLSlimVSH glDisableVertexAttribArray_nid_postfix
libSceGLSlimVSH glDisable_nid_postfix
libSceGLSlimVSH glEnableVertexAttribArray_nid_postfix
libSceGLSlimVSH glEnable_nid_postfix
libSceGLSlimVSH glFinish_nid_postfix
libSceGLSlimVSH glFlush_nid_postfix
libSceGLSlimVSH glFramebufferRenderbuffer_nid_postfix
libSceGLSlimVSH glFramebufferTexture2D_nid_postfix
libSceGLSlimVSH glFrontFace_nid_postfix
libSceGLSlimVSH glGenBuffers_nid_postfix
libSceGLSlimVSH glGenFramebuffers_nid_postfix
libSceGLSlimVSH glGenRenderbuffers_nid_postfix
libSceGLSlimVSH glGenTextures_nid_postfix
libSceGLSlimVSH glGenerateMipmap_nid_postfix
libSceGLSlimVSH glGetAttachedShaders_nid_postfix
libSceGLSlimVSH glGetBooleanv_nid_postfix
libSceGLSlimVSH glGetBufferParameteriv_nid_postfix
libSceGLSlimVSH glGetError_nid_postfix
libSceGLSlimVSH glGetFloatv_nid_postfix
libSceGLSlimVSH glGetFramebufferAttachmentParameteriv_nid_postfix
libSceGLSlimVSH glGetIntegerv_nid_postfix
libSceGLSlimVSH glGetProgramInfoLog_nid_postfix
libSceGLSlimVSH glGetProgramiv_nid_postfix
libSceGLSlimVSH glGetRenderbufferParameteriv_nid_postfix
libSceGLSlimVSH glGetShaderInfoLog_nid_postfix
libSceGLSlimVSH glGetShaderiv_nid_postfix
libSceGLSlimVSH glGetTexParameterfv_nid_postfix
libSceGLSlimVSH glGetTexParameteriv_nid_postfix
libSceGLSlimVSH glGetVertexAttribPointerv_nid_postfix
libSceGLSlimVSH glGetVertexAttribfv_nid_postfix
libSceGLSlimVSH glGetVertexAttribiv_nid_postfix
libSceGLSlimVSH glHint_nid_postfix
libSceGLSlimVSH glIsBuffer_nid_postfix
... 38 more
⚪ 3 behaviourally empty (constant return or throw)
Library Name
libSceGLSlimVSH eglQueryAPI_nid_postfix
libSceGLSlimVSH eglWaitClient_nid_postfix
libSceGLSlimVSH eglWaitGL_nid_postfix
🆕 35 declared as stubs
Library Name
libSceGLSlimVSH eglCreateWindowSurface_nid_postfix
libSceGLSlimVSH glDrawArrays_nid_postfix
libSceGLSlimVSH glGetActiveAttrib_nid_postfix
libSceGLSlimVSH glGetActiveUniform_nid_postfix
libSceGLSlimVSH glGetAttribLocation_nid_postfix
libSceGLSlimVSH glGetString_nid_postfix
libSceGLSlimVSH glGetUniformLocation_nid_postfix
libSceGLSlimVSH glLinkProgram_nid_postfix
libSceGLSlimVSH glOrbisMapTextureResourceSCE_nid_postfix
libSceGLSlimVSH glOrbisTexImageCanvas2DSCE_nid_postfix
libSceGLSlimVSH glOrbisTexImageResourceSCE_nid_postfix
libSceGLSlimVSH glOrbisUnmapTextureResourceSCE_nid_postfix
libSceGLSlimVSH glShaderBinary_nid_postfix
libSceGLSlimVSH glUniform1f_nid_postfix
libSceGLSlimVSH glUniform1i_nid_postfix
libSceGLSlimVSH glUniformMatrix4fv_nid_postfix
libSceGLSlimVSH scePigletAllocateSystemMemoryEx
libSceGLSlimVSH scePigletAllocateVideoMemoryEx
libSceGLSlimVSH scePigletGetConfigurationVSH
libSceGLSlimVSH scePigletReleaseSystemMemoryEx
libSceGLSlimVSH scePigletReleaseVideoMemoryEx
libSceGLSlimVSH scePigletSetConfigurationVSH
libSceGLSlimVSH sceSlimglClientStartIPC
libSceGLSlimVSH sceSlimglCompositorAllocateIndex
libSceGLSlimVSH sceSlimglCompositorCreateIndirectRenderTarget
libSceGLSlimVSH sceSlimglCompositorDeleteIndirectRenderTarget
libSceGLSlimVSH sceSlimglCompositorFlush
libSceGLSlimVSH sceSlimglCompositorFlushWithRepeat
libSceGLSlimVSH sceSlimglCompositorGetCanvasHandle
libSceGLSlimVSH sceSlimglCompositorGetError
libSceGLSlimVSH sceSlimglCompositorReleaseIndex
libSceGLSlimVSH sceSlimglCompositorSetEndOfFrameCommand
libSceGLSlimVSH sceSlimglCompositorSetIndirectCanvasCommand
libSceGLSlimVSH sceSlimglCompositorSetIndirectCompositionCommand
libSceGLSlimVSH sceSlimglCompositorSetIndirectRenderTargetConfigCommand
🗑️ 22 removed
Library Name
libSceGLSlimVSH sceGLSlimVSHUnknown_1TFdFqQBGqY_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_3gtNzvkq_XY_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_6ZQXcSKKjyo_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_7Mp6qE235Qc_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_AcruVcmKz78_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_BrNgn7z6A40_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_CzmA_OALrH8_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_J5IG3lL56FI_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_LuP1plTAR7g_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_QvXbiLqpn6c_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_RP5cXUjm48U_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_T__xooU3VvQ_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_aRqvgeH_oe0_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_gI_XEd5mWPU_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_hA8TWZkwPRU_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_iIsF4NzYgD4_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_iyTnezpw1jE_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_mgKTS0PIvd8_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_oXkQEVitkCs_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_sDotUt1uEhA_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_srJHx3p48v0_nid_no_patch
libSceGLSlimVSH sceGLSlimVSHUnknown_wdRBDMIxI7I_nid_no_patch

Changed libraries (implemented exports)

Library Before After Change
libSceGLSlimVSH 0/163 (0.00%) 138/210 (65.71%) +65.71%

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 6521 eglBindAPI
eglChooseConfig
eglCreateContext
eglCreateWindowSurface
eglDestroyContext
eglDestroySurface
eglGetDisplay
eglGetError
eglInitialize
eglMakeCurrent
eglSwapBuffers
eglSwapInterval
eglTerminate
glActiveTexture
glAttachShader
glBindTexture
glBlendFunc
glClear
glClearColor
glCreateProgram
glCreateShader
glDeleteProgram
glDeleteShader
glDeleteTextures
glDrawArrays
glEnable
glEnableVertexAttribArray
glGenTextures
glGetActiveAttrib
glGetActiveUniform
glGetAttribLocation
glGetError
glGetProgramiv
glGetString
glGetUniformLocation
glLinkProgram
glPixelStorei
glShaderBinary
glTexImage2D
glTexParameteri
glUniform1f
glUniform1i
glUniformMatrix4fv
glUseProgram
glVertexAttribPointer
glViewport
scePigletSetConfigurationVSH

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 14212 docs/dev/debt/libSceGLSlimVSH.md

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests run and reviewed — approval deferred

On unchanged head 7c21f2a91eed4f72537466a931fee7951b22553e, Windows CI compiled and linked the new library, but did not execute its new guest_glslim_state test; Linux was skipped.

What I ran

Refreshed PR state and checks for head 7c21f2a91eed4f72537466a931fee7951b22553e (PR base 02c8efdbcba38f173309ca733bc88bcb473b1f1f) and inspected the successful Windows job log. This was hosted CI on Windows with MinGW GCC 15.2.0; I did not build locally.

gh pr checks 13868 --repo boykopovar/AnyPS5
gh run view 41192298621 --repo boykopovar/AnyPS5 --json workflowName,headSha,jobs
gh run view 41192298621 --repo boykopovar/AnyPS5 --job 124512574770 --log

Results

Check Result
Windows compile/link Passed for libSceGLSlimVSH.prx at the reviewed head.
Windows CTest No PR-specific test ran; the job log says no guest core/libs test sources changed. The PR adds tests/State.cpp and registers guest_glslim_state, but the workflow did not select it.
Hosted conventions, intake, labels, eligibility, report, and library portability Passed.
Linux and specialized jobs Skipped by the workflow.
Relevant unedited Windows job output
windows	Link changed host-only core/libs test executables	2026-10-31T10:31:55.6490652Z OK: D:/a/AnyPS5/AnyPS5/build/core/libs/libs/libSceGLSlimVSH.prx
windows	Build and run changed guest core/libs tests	2026-10-31T10:32:07.4094268Z No guest core/libs test sources changed
windows	Build and run changed guest core/libs tests	2026-10-31T10:32:07.4094929Z No guest core/libs test sources changed; the libs build still ran

Negative control

No negative control was run by me.

Findings

Blocking: None confirmed in the source review.

Non-blocking: The new state test has not been shown running on the reviewed head. Because this is a large EGL/GLES implementation, compile and source inspection alone do not establish the added state and object behavior; I am withholding approval until there is a successful run of guest_glslim_state or equivalent exact-head evidence.

Sources

Not verified

No exact-head CTest run, Linux execution, console behavior, or GPU-backed EGL/GLES behavior was verified.

To get this to a good state

Please provide a successful exact-head guest_glslim_state run or fix the test selection so CI executes it. I will re-check the same test and the current head before changing the review status.

@PrivacyOnion

Copy link
Copy Markdown
Author

@THEMANnt Thanks, fixed in c886768. tests/State.cpp no longer includes src/State.hpp or touches Slim::thread / Slim::Current_nid_no_patch; it goes through the exported EGL/GLES entry points only, so the registered target links against the shared library without importing its TLS. The texture checks now read pixels back through a framebuffer with glReadPixels (byte RGB at unpack alignment 8 and packed 565, plus the incomplete-attachment status after a GL_LUMINANCE_ALPHA upload); the buffer-contents, depth/stencil and mip-level-1 assertions, which GLES2 cannot observe, are dropped. Checked by building the library as a host-ABI DLL and linking the test executable against it: passes, and nm -u on the test object lists no Slim:: symbols (the previous version imported Slim::thread). My local MinGW GCC 13.1 uses emulated TLS, so it did not reproduce the SECREL failure; the hosted Windows build will confirm with the project toolchain.

@THEMANnt THEMANnt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked c886768: my Windows TLS link finding is resolved.

The unchanged registered test now builds against the shared library and passes on the same MSYS2 GCC 16.2 toolchain that reproduced the original failure. All 14 independent public API checks also pass, and nm -u confirms no Slim:: references remain in the test object.

The replacement texture checks exercise public framebuffer readback. The removed internal buffer, depth/stencil and mip-level assertions are no longer covered by this fixture.

No new actionable issue found in this follow-up. Hosted Build is still running; these local checks used an isolated harness, not the full libc/game runtime.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — new head, approval deferred

At c886768ca21c46fae090530790e1536c0b220674, the prior direct DLL thread-local access is gone and Windows builds the library, but CI still skips guest_glslim_state, so the new behavior remains unverified.

What I ran

Reviewed the current head c886768ca21c46fae090530790e1536c0b220674 against PR base fd31320e83fe417fa9c7fef792613653d9eb4f02; the precheck's merge preview was clean against that base. Environment: Linux x86_64, Python 3.11.2, GCC 12.2.0. No local build or test was run.

git diff --check 7c21f2a91eed4f72537466a931fee7951b22553e..c886768ca21c46fae090530790e1536c0b220674
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13868
python3 tools/pr_abi_audit.py --repo /marc/AnyPS5 --base fd31320e83fe417fa9c7fef792613653d9eb4f02 --head c886768ca21c46fae090530790e1536c0b220674 --json
gh run view 41193779027 --repo boykopovar/AnyPS5 --job 124516189665 --log

Results

Check Result
Updated test diff The direct Slim::thread access flagged on the old head was removed. The changes also replace internal buffer/depth/stencil value assertions with glGetError()==0, so those values are no longer asserted by this test.
Diff and conventions Passed.
ABI audit Passed with warnings: 232 symbols inspected; warnings are the placeholder export names replaced by the names documented in the PR. This audit does not validate runtime ABI.
Merge preview Clean against the stated PR base.
Hosted Windows Library compilation and link passed. The registered guest_glslim_state test did not run.
Hosted Linux and specialized jobs Skipped. Other reported policy checks passed.
Unedited Windows CI output
windows	Link changed host-only core/libs test executables	2026-10-31T10:51:00.0640482Z [2303/2882] Linking CXX shared library core\libs\libs\unpatched\libSceGLSlimVSH.prx
windows	Link changed host-only core/libs test executables	2026-10-31T10:51:20.7784969Z OK: D:/a/AnyPS5/AnyPS5/build/core/libs/libs/libSceGLSlimVSH.prx
windows	Build and run changed guest core/libs tests	2026-10-31T10:51:32.1525509Z No guest core/libs test sources changed
windows	Build and run changed guest core/libs tests	2026-10-31T10:51:32.1526244Z No guest core/libs test sources changed; the libs build still ran

Findings

Blocking

None confirmed in the source review.

Non-blocking

CI did not execute the new test, and its current replacement assertions do not verify the buffer, depth, or stencil values that the removed internal assertions checked. The PR description reports a host-ABI MinGW test run, but I did not reproduce it.

Sources

Not verified

I did not run guest_glslim_state, build locally, test Linux, or verify GPU, title, or console behavior. The author's reported MinGW test result is not independently confirmed.

To get this to a good state

Please provide a successful exact-head guest_glslim_state run and retain meaningful assertions for the buffer and depth/stencil state covered before the update. I will re-run the relevant checks on the new head.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@PrivacyOnion, three changes are needed on 7c21f2a91e:

  1. In Images.cpp:532, col * 4 is evaluated as signed int before it is added to the byte offset. With a 1 × 1 red pbuffer, glReadPixels(-536870912, 0, 536870913, 1, GL_RGBA, GL_UNSIGNED_BYTE, dst) reaches the valid pixel at column 536870912 and UBSan reports signed integer overflow. My destination was a valid 2,147,483,652-byte virtual mapping; it did not require resident storage for the out-of-bounds pixels. Converting col to size_t before multiplying makes the same check write the correct last pixel. Please calculate the pixel offsets in a sufficiently wide type and add a bounded regression for this boundary.
  2. In Egl.cpp:133, a null attribute list requests the default ES1 context, but the sole configuration only advertises ES2. This currently returns EGL_BAD_MATCH (0x3009). EGL 1.4, section 3.7.1 requires EGL_BAD_CONFIG (0x3005) when the configuration does not support the requested client API version. Please correct the error and cover the default-version request.
  3. In tests/State.cpp:191–196, please remove the assertion that a valid glCompileShader call throws. Tests should not require an unimplemented call to remain unimplemented. Keep the initial shader-status, source, attachment and lifetime checks.

The submitted state test passes in my Linux host-ABI UBSan check. All 138 implemented signatures match the standard headers, and their NIDs match the pinned catalogue. These checks do not establish console behavior.

@PrivacyOnion

Copy link
Copy Markdown
Author

Updated in 411e17c.

@oneandonlydean

  • glReadPixels now computes destination offsets in size_t and only visits the columns and rows that intersect the source image, so no int product is formed; Upload uses the same widened offsets. Regression: reading (-2, 0, 3, 1) from the red 4x3 pbuffer writes only bytes 8-11, and (-536870912, 0, 1, 1) writes nothing. The exact 536870913-wide case needs a ~2 GiB destination, so it is not in the fixture. Checked with the library built with -ftrapv (host-ABI DLL, MinGW GCC 13.1): passes.
  • eglCreateContext returns EGL_BAD_CONFIG for a client version the configuration does not support, including the default ES1 request from a null attribute list (EGL 1.4 §3.7.1); covered in the test.
  • The assertion that glCompileShader throws is removed; the status, source length, attachment and lifetime checks stay.

@MarcZX10 The Windows job skipped the test because tools/build_changed_guest_tests.py selected no guest test at all: its log prints the same "No guest core/libs test sources changed" for #13500 and for the merged #13564, whose test lives in core/libs/tests/, so the selection gap is not specific to this PR and fixing it belongs in a separate change. For exact-head evidence on c886768, @THEMANnt built the unchanged registered guest_glslim_state target against the shared library with MSYS2 GCC 16.2 and it passed. The buffer contents and depth/stencil values the earlier fixture read are not observable through GLES2 (no glGetBufferSubData, glReadPixels reads colour only), so a test that links the shared library cannot assert them; the clear values are still checked through glGet*.

@PrivacyOnion

Copy link
Copy Markdown
Author

Follow-up in ea0fcca: the fixture now also asserts the depth and stencil clear values through glGetFloatv(GL_DEPTH_CLEAR_VALUE) and glGetIntegerv(GL_STENCIL_CLEAR_VALUE) (previously only the colour clear value was checked), so the statement above holds.

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux run of head ea0fccaf7, merged (--no-commit) onto main 85cdddc1b0, in the full tree through the new add_test block (not a standalone build). Ubuntu 26.04 (kernel 7.0), GCC 15.2.0, CMake 4.2.3, Ninja, Release, BUILD_TESTING=ON, i7-8700.

  • guest_glslim_state builds and passes 3/3, including the worker-thread context and surface cases. Full build ok, public_headers 65/65 (the PR touches Api.hpp and InventoryExports.hpp).
  • Red, keeping the test: dropping the clamp from glClearColor's stored state in GlState.cpp makes it abort at line 63 3/3.
  • The earlier heads 7c21f2a91 (on main cf5a1805e5) and 411e17ced gave the same results.

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — new head, looks good

At ea0fccaf769f7f9f00c4ccbaacf1318636ebcc4e, the test now covers depth/stencil queries and clipped pixel reads, and I found no remaining blocking issue.

What I ran

Reviewed head ea0fccaf769f7f9f00c4ccbaacf1318636ebcc4e against base 85cdddc1b0e89fe66744f437513ccfdcb16f72f6; the merge preview was clean. Environment: Linux x86_64, Python 3.11.2. I did not build locally.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13868
python3 tools/pr_abi_audit.py --base 85cdddc1b0e89fe66744f437513ccfdcb16f72f6 --head ea0fccaf769f7f9f00c4ccbaacf1318636ebcc4e --json

Results

Check Result
Diff and conventions Passed
Source-level ABI audit 232 symbols inspected; 22 warnings identify the old placeholder export names replaced by named exports; no other mismatch reported
Test evidence A PR participant reports the full Linux build and guest_glslim_state passed 3/3 on this exact head, public_headers passed 65/65, and removing the glClearColor clamp made the test fail 3/3
Hosted CI Eligibility, conventions, portability, labels and report passed; Linux and specialized build jobs were skipped; Windows was still running at the final status check
Local convention and ABI-audit summaries
All conventions checks passed.
status: passed_with_warnings
symbols: 232
findings: 22
warnings: 0

Negative control

Assertion Change to code under test Outcome
The state test detects incorrect glClearColor storage The PR participant reports removing the clamp in GlState.cpp Test aborted 3/3, as expected; I did not run this mutation myself

Sources

Not verified

I did not compile or run tests locally, and Windows CI had not finished. No physical-console or GPU-driver behavior was verified.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — changes requested

I am correcting my earlier approval because this head lets eglSwapBuffers succeed for a valid surface that is not the current thread's draw surface.

What I ran

Reviewed head ea0fccaf769f7f9f00c4ccbaacf1318636ebcc4e against PR base 85cdddc1b0e89fe66744f437513ccfdcb16f72f6. The live merge preview was clean against current target tip 73f4f7e06e4f210a8c6570e335fd654dc0a86134. Environment: Linux x86_64, Python 3.11.2, GCC 12.2.0. No project build or compilation was run.

git diff --check 85cdddc1b0e89fe66744f437513ccfdcb16f72f6...ea0fccaf769f7f9f00c4ccbaacf1318636ebcc4e
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13868
python3 tools/pr_abi_audit.py --base 85cdddc1b0e89fe66744f437513ccfdcb16f72f6 --head ea0fccaf769f7f9f00c4ccbaacf1318636ebcc4e --json > /tmp/anyps5-13868-abi.json
python3 -c 'import json; from collections import Counter; d=json.load(open("/tmp/anyps5-13868-abi.json")); print("status:", d["status"]); print("symbols:", len(d["symbols"])); print("findings:", len(d["findings"])); print(Counter(x["kind"] for x in d["findings"]))'
python3 /marc/AnyPS5/tools/pr_test_quality.py --root /tmp/anyps5-review-13868 --json core/libs/prx/libSceGLSlimVSH/tests/State.cpp
gh pr checks 13868 --repo boykopovar/AnyPS5

Results

Check Result
Diff check Passed; no output.
Conventions and PR template Passed.
ABI audit passed_with_warnings; 232 symbols inspected and 22 export-removed warnings correspond to the old placeholder names replaced in this PR. This lexical audit does not certify binary ABI or runtime behavior.
Test-quality heuristic Flagged the C++ test as possibly unregistered. I inspected the PR's CMake file: tests/State.cpp is passed to add_test_executable and registered as guest_glslim_state, so this heuristic finding is a false positive.
Precheck runner Partial: its temporary head worktree does not contain the local-only pr_abi_audit.py and pr_test_quality.py helper scripts, so those two subchecks could not launch there. I ran both helpers separately against the pinned head/worktree as shown above.
Hosted CI Windows, conventions, eligibility, library-portability, labels and report passed; Linux and specialized jobs were skipped.
Selected unedited check output
All conventions checks passed.
status: passed_with_warnings
symbols: 232
findings: 22
Counter({'export-removed': 22})
{
  "findings": [
    {
      "path": "core/libs/prx/libSceGLSlimVSH/tests/State.cpp",
      "line": 1,
      "kind": "possible-unregistered-cpp-test",
      "message": "Changed C++ test source path was not found literally in CMake files; inspect registration, generated source lists, and workflow coverage."
    }
  ],
  "negative_control_candidates": [],
  "limits": [
    "Heuristics can miss weak assertions and can flag valid tests; inspect every finding.",
    "A test that passes against base is not by itself proof that the PR test is inadequate.",
    "Negative controls are only candidates until the test actually runs against base and fails by assertion rather than import/setup error."
  ]
}
labels	pass	12s	https://github.com/boykopovar/AnyPS5/actions/runs/41195244607/job/124520830916
windows	pass	7m25s	https://github.com/boykopovar/AnyPS5/actions/runs/41195247263/job/124520910723
linux	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41195247263/job/124520912157
register-context	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41195247263/job/124520911759
relinker	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41195247263/job/124520911638
relinker-asan	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41195247263/job/124520912338
write-watch	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41195247263/job/124520912057
conventions	pass	21s	https://github.com/boykopovar/AnyPS5/actions/runs/41195244515/job/124519989534
eligibility	pass	6s	https://github.com/boykopovar/AnyPS5/actions/runs/41195247263/job/124519997679
library-portability	pass	1m11s	https://github.com/boykopovar/AnyPS5/actions/runs/41195247418/job/124519995347
report	pass	54s	https://github.com/boykopovar/AnyPS5/actions/runs/41195247337/job/124519995226

Findings

Blocking

eglSwapBuffers_nid_postfix at src/Egl.cpp:320-323 checks only that the display and surface are valid. It returns EGL_TRUE even when that surface is not bound as the calling thread's current draw surface. EGL 1.4 §3.10.4 requires EGL_BAD_SURFACE in that case. For example, while surface is current, swapping the valid otherSurface created in the test should fail with EGL_BAD_SURFACE (0x300d), but this implementation returns success. Please require the supplied surface to equal thread.draw and add that regression assertion.

Non-blocking

None identified in this focused re-check.

Sources

Not verified

I did not build locally or run guest_glslim_state; the hosted Linux and specialized jobs were skipped. No GPU, title, or physical-console behavior was verified. The PR's reported Windows test and another participant's reported Linux test were not rerun by me.

To get this to a good state

Please validate the current draw-surface binding in eglSwapBuffers and add the second-pbuffer regression case. I will rerun the same no-build checks and review the new exact head.

@PrivacyOnion

Copy link
Copy Markdown
Author

@MarcZX10 Fixed in 5c9bb73: eglSwapBuffers now returns EGL_BAD_SURFACE unless the surface is the calling thread's current draw surface (EGL 1.4 §3.9.3), which also covers a thread with no current context. Regression in tests/State.cpp: with surface current, swapping surface succeeds, swapping the valid otherSurface fails with 0x300d, and the same call from the worker thread before it binds anything fails with 0x300d. The test passes against the library built as a DLL, both files compile to objects with the real APS5_VABI, and conventions pass.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — new head, looks good

The new current-draw-surface check and regression cases resolve the reported eglSwapBuffers defect.

What I ran

Reviewed exact head 5c9bb732b80b2119779a7dacda8a768ffbd996c8 against the PR base 474030e58424fefdb65e5df9f3820810fbb4553c; the no-build merge preview was clean against current main 1cac0ca433924cda6be37f4f7e460c356e36ae93. I inspected eglSwapBuffers and its added current-surface and worker-thread assertions. I did not build or run the C++ test locally.

python3 /root/.codex/skills/anyps5-pr-review/scripts/pr_snapshot.py 13868 --repo boykopovar/AnyPS5
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13868 --output-dir /tmp/anyps5-13868-rereview-5c9bb
gh api repos/boykopovar/AnyPS5/commits/5c9bb732b80b2119779a7dacda8a768ffbd996c8/check-runs

Results

Check Result
Diff check and conventions Passed
Current-main merge preview Clean
Hosted Windows job Passed; this does not establish that the focused state test ran in CI
Author-reported guest_glslim_state DLL test and APS5_VABI object compilation Passed; not independently reproduced
Hosted Linux and specialized jobs Skipped

Findings

Blocking

None found in this re-check.

Non-blocking

The focused EGL state test is author-reported, not independently reproduced. Linux and console behavior remain unverified.

Sources

Not verified

I did not run a local build or guest_glslim_state, Linux runtime tests, or console behavior. Linux and specialized hosted jobs were skipped.

@THEMANnt THEMANnt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed 5c9bb732b80b2119779a7dacda8a768ffbd996c8. My earlier DLL TLS test-link blocker remains fixed. Reviewed the subsequent context-version error, readback offset/intersection, swap-surface validation and test changes. No new actionable issue found in this follow-up.

Windows/MSYS2 GCC 16.2 Release: the unmodified registered DLL-linked state test passes. Sixteen independent checks pass, including separate read/draw surfaces, pack stride, buffer bounds, cube mipmaps, deferred context deletion and the exact sparse 2 GiB destination reproducer for the readback-offset boundary. Hosted Windows actually built and ran guest_glslim_state on this head; its selected run passed 2,524/2,524 tests. Whitespace passes. Local builds use minimal throwing libc support; no title, console, GPU rendering or complete GLES conformance claim is made.

@adriadam10 adriadam10 self-assigned this Nov 1, 2026

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The full Windows Build on 5c9bb732b8 fails prx_thread_local_destructors (run 41274748741); main passes it.

  • src/State.cpp:6 / src/State.hpp:129: thread_local ThreadState thread holds shared_ptrs, so it registers a thread_local destructor. On Windows that destructor runs after the emulated TLS freed the object. The test reports libSceGLSlimVSH.prx: _ZTHN4Slim6threadE registers a thread_local destructor and the helpers that touch it (Current, Error, EglError, Display, Config, Complete, Color, Query).
  • Fix: keep the per-thread state in HostThreadLocal<ThreadState, ThreadTag>() (core/libs/prx/libc/include/HostThreadLocal.hpp, same pattern as libkernel/Module/src/DynamicLoader.cpp:40) and reach it through an accessor instead of the thread global. Then ctest -R prx_thread_local_destructors should pass.
  • Nothing else changed in my review; the earlier approvals still apply to the rest.

…and pbuffer storage

Implement the EGL 1.4 and OpenGL ES 2.0 exports that do not need a shader compiler or rasterizer as a host-side state machine following the Khronos specifications: the default display, a single RGBA8/depth16/stencil8 pbuffer configuration, ES2 contexts with share groups, per-thread current state and errors, buffers, textures with mipmap generation, renderbuffers, framebuffers and their completeness, shader and program objects, vertex attributes, every fixed-function state setter and query, clears, pixel uploads, copies and reads on CPU storage.

The 22 unknown NIDs are named from the NID database and the Piglet, Orbis texture and compositor exports, together with shader compilation, program linking and reflection, uniforms, draws, native window surfaces and the Sony-specific APIs, stay NotImplemented_nid_no_patch; the gaps are in docs/dev/debt/libSceGLSlimVSH.md.
@PrivacyOnion

Copy link
Copy Markdown
Author

@adriadam10 thanks, fixed in 19af8ed. The per-thread state is no longer a thread_local global: Slim::Thread() returns HostThreadLocal<ThreadState, ThreadTag>() (core/libs/prx/libc/include/HostThreadLocal.hpp, as in libkernel's DynamicLoader), and every former thread. use in Egl.cpp, Images.cpp and State.cpp goes through it, so on Windows the state lives in an FLS slot whose callback deletes it.

Checked with the same criterion as tests/ThreadLocalDestructors.cmake: compiled with the real APS5_VABI and the CI flags, the previous State.cpp object references __cxa_thread_atexit and none of the six library objects does now. The state test (library built as a DLL, test linked against it, including the worker-thread context/surface cases, where the FLS callback runs at thread exit) passes, and conventions and the public-header audit pass. My local toolchain is MinGW GCC 13.1, so the full Windows build will confirm prx_thread_local_destructors.

@adriadam10
adriadam10 merged commit 41b72cc into boykopovar:main Nov 1, 2026
11 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the prx_thread_local_destructors fix: the per-thread state now goes through HostThreadLocal<ThreadState, ThreadTag>() (FLS slot with a deleting callback on Windows), no thread_local is left in the library, and the earlier review points remain addressed; merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants