Skip to content

feat(libScePigletv2VSH): implement the EGL and GLES 2 calls of the piglet sample - #6521

Open
Get-fix wants to merge 3 commits into
boykopovar:mainfrom
Get-fix:ps4/libscepigletv2vsh
Open

Get-fix wants to merge 3 commits into
boykopovar:mainfrom
Get-fix:ps4/libscepigletv2vsh

Conversation

@Get-fix

@Get-fix Get-fix commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

What

The OpenOrbis piglet sample renders through the PS4 GLES library libScePigletv2VSH, which AnyPS5 does not have. It imports 47 functions from it: scePigletSetConfigurationVSH, 13 EGL 1.4 functions and 33 OpenGL ES 2.0 functions. It loads the library and libScePrecompiledShaders with sceKernelLoadStartModule and passes the shaders from #6520 to glShaderBinary.

This adds libScePigletv2VSH with those 47 functions on Vulkan. The first commit is #6520; this pull request adds the second one.

  • Shaders: glShaderBinary takes AnyPS5's GLSL ES source from feat(libScePrecompiledShaders): export the texmap shaders the piglet sample uses #6520; glLinkProgram compiles it with glslang to SPIR-V, packs the loose uniforms into one uniform buffer and binds the samplers as combined image samplers. A PS4 shader binary throws.
  • Drawing: draws are recorded into one render pass per frame, with pipelines cached by their state. Client-side vertex arrays, blending, viewports, glPixelStorei unpack alignment and the GL_RGBA, GL_RGB, GL_LUMINANCE, GL_LUMINANCE_ALPHA and GL_ALPHA texel formats are handled. A texture whose minifying filter needs mipmaps it does not have samples as incomplete, as OpenGL ES requires. The Y axis is flipped with a negative viewport height, and OpenGL's clip-space depth is kept where the device has VK_EXT_depth_clip_control.
  • Presenting: eglCreateWindowSurface opens a VideoOut port and registers two linear R8G8B8A8 buffers. eglSwapBuffers copies the frame into the next buffer once no flip is pending and submits the flip, on vblank for swap interval 1 and on hsync for 0. The sample calls eglSwapInterval before it has a context, so that call succeeds and sets the interval of the next surface.
  • Errors: invalid arguments set the EGL or GL error, and glGetError and eglGetError report it. What the sample does not use throws, among it cube maps, mipmap levels other than 0, texel types other than GL_UNSIGNED_BYTE, shared contexts and GL_LINE_LOOP; eglChooseConfig finds no config with depth or stencil.
  • Linking on MinGW: libc's import library is linked before glslang, and libstdc++ before the import library's trailing copy. The C++ runtime (__cxa_throw, _Unwind_*) then binds to libc.prx, so exceptions thrown here reach the caller's handlers. glslang's std::string members bind to libstdc++, because the import library lists 12 of them that libc.prx does not export, which made the library fail to load with error 127.

The limits are in the new docs/dev/debt/libScePigletv2VSH.md. Part of the PS4 homebrew work tracked in #3093.

Tested

Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7, Release, BUILD_TESTING=ON, on main 03c4cb5e7:

  • The new guest_piglet test creates a 64x64 offscreen surface, links the two shaders from the table and renders five frames, checking pixels in each: a 2x2 RGBA texture on the left half (the four texels in place and the clear colour elsewhere); the same with opacity 0.5 and GL_SRC_ALPHA blending; a mipmapping filter without mipmaps (black); a 32x32 viewport; an RGB texture with the default 4-byte row alignment. It also checks EGL initialization, config choice, eglSwapInterval without a context, the reflected attribute and uniforms, the GL errors of invalid calls, and that a PS4 shader binary throws an exception the test catches.
  • Each of these makes the test fail: no Y flip, blending never enabled, sampling a texture that needs missing mipmaps, ignoring unpack alignment, RGB expanded with alpha 0, ignoring glViewport, writing glUniform1f at offset 0, accepting a PS4 binary as source, eglSwapInterval failing without a context.
  • The patched libScePigletv2VSH.prx exports exactly the 47 functions the sample imports, and imports from libc.prx only functions the patched libc.prx exports.
  • The OpenOrbis piglet sample on main 03c4cb5e7 with this, feat(libkernel): load system libraries from their console paths #6519, fix(relinker): search libc.prx for libkernel-only Windows executables #5990 to fix(relinker): stop module syscall scans at the PLT and skip the PS4 loader path #5994, feat(libSceFreeType): implement the six FreeType functions OpenOrbis samples use #6376, fix(relinker): accept section-relative guest module relocations #5138 and a change that answers the Linux TIOCGWINSZ with ENOTTY, as fix(libkernel): return ENOTTY for malformed ioctl requests #5569 did: it loads both modules, prints GL_RENDERER: AnyPS5 Piglet on Vulkan, finds both shaders and draws its rotating textured square at 59.96 FPS (window title OpenOrbis piglet sample | FPS: 59.96 (666)). With neither library, it stops at start-up with 48 FAIL: unresolved ELF import lines, one for each function and one for scePrecompiledShaderEntries. The 14 other samples that start with my open pull requests still start.
  • Full ctest of this branch on main 03c4cb5e7: 1296 of 1300 pass. agc_driver_gpu_indirect_arguments_misaligned_writer_ahead does not compile with MinGW on main (test(agc): align the indirect arguments block at run time #6452 fixes it), and prx_thread_local_destructors fails as it did on main 92cdc7b62 on this machine without my changes; agc_shader_disk_cache (timeout) and agc_driver_multisample_fill_host_only failed under ctest -j8 and pass when run alone. Full ctest of the build with all my open pull requests: 1304 of 1306 pass; the two that do not are the first two above.
  • tools/check_conventions.py passes.

Not tested on Linux or macOS.

Checklist

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Progress report (cecb540 → 95b1f00)

📈 System libraries: 42.35% (+0.25%, +47 implemented functions)

✅ 47 implemented
Library Name
libScePigletv2VSH eglBindAPI
libScePigletv2VSH eglChooseConfig
libScePigletv2VSH eglCreateContext
libScePigletv2VSH eglCreateWindowSurface
libScePigletv2VSH eglDestroyContext
libScePigletv2VSH eglDestroySurface
libScePigletv2VSH eglGetDisplay
libScePigletv2VSH eglGetError
libScePigletv2VSH eglInitialize
libScePigletv2VSH eglMakeCurrent
libScePigletv2VSH eglSwapBuffers
libScePigletv2VSH eglSwapInterval
libScePigletv2VSH eglTerminate
libScePigletv2VSH glActiveTexture
libScePigletv2VSH glAttachShader
libScePigletv2VSH glBindTexture
libScePigletv2VSH glBlendFunc
libScePigletv2VSH glClear
libScePigletv2VSH glClearColor
libScePigletv2VSH glCreateProgram
libScePigletv2VSH glCreateShader
libScePigletv2VSH glDeleteProgram
libScePigletv2VSH glDeleteShader
libScePigletv2VSH glDeleteTextures
libScePigletv2VSH glDrawArrays
libScePigletv2VSH glEnable
libScePigletv2VSH glEnableVertexAttribArray
libScePigletv2VSH glGenTextures
libScePigletv2VSH glGetActiveAttrib
libScePigletv2VSH glGetActiveUniform
libScePigletv2VSH glGetAttribLocation
libScePigletv2VSH glGetError
libScePigletv2VSH glGetProgramiv
libScePigletv2VSH glGetString
libScePigletv2VSH glGetUniformLocation
libScePigletv2VSH glLinkProgram
libScePigletv2VSH glPixelStorei
libScePigletv2VSH glShaderBinary
libScePigletv2VSH glTexImage2D
libScePigletv2VSH glTexParameteri
libScePigletv2VSH glUniform1f
libScePigletv2VSH glUniform1i
libScePigletv2VSH glUniformMatrix4fv
libScePigletv2VSH glUseProgram
libScePigletv2VSH glVertexAttribPointer
libScePigletv2VSH glViewport
libScePigletv2VSH scePigletSetConfigurationVSH

@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.

A Linux run, since the description lists none.

Machine: NVIDIA GeForce RTX 3070, driver 595.99.02, Vulkan 1.4.329, Ubuntu 26.04 (kernel 7.0.0-38), i7-8700. GCC 15.2, Release, BUILD_TESTING=ON. Head e983d881f merged onto main 31cbb55d7, no conflicts. After reconfiguring for the new library, the build finishes with no warnings.

GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02), Linux; llvmpipe (Mesa 26.0.3), Linux

  • guest_piglet and guest_precompiled_shaders pass 3/3 with ANYPS5_GPU="NVIDIA GeForce RTX 3070", 3/3 with ANYPS5_GPU=llvmpipe, and 3/3 with ANYPS5_GPU unset (both ICDs installed). With ANYPS5_GPU=NoSuchGPU, guest_piglet is skipped with no Vulkan 1.1 graphics device matches ANYPS5_GPU=NoSuchGPU, so the selector filters on Linux as well. The 3070 exposes VK_EXT_depth_clip_control, so that path is the one taken here.
  • Fault check on this driver: with the Y flip taken out of the draw viewport in Context.cpp (origin viewport[1], positive height), guest_piglet fails on the RTX 3070 at the first frame's texel check (Piglet check failed at line 204). With the flip restored, it passes.
  • ctest -R "^agc" -E "agc_display_buffer_dcc|agc_driver_flip|agc_driver_lds_atomics64" -j1 --timeout 60: 591/593 pass, the same result as unchanged main on this machine. agc_driver_stencil_ref_export is skipped (no VK_EXT_shader_stencil_export), and agc_driver_store_over_untracked fails as it does on main (#6385).

I did not run the OpenOrbis piglet sample itself.

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

@Get-fix

Get-fix commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for the thorough Linux run, @jotitadev: two GPUs, the ANYPS5_GPU selector, and the fault check with the Y flip taken out. It's good to know the VK_EXT_depth_clip_control path works on the RTX 3070, and that llvmpipe passes too.

AI-assisted: yes (Claude Code).

🤖 Generated with Claude Code

@javierUDP javierUDP 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.

Static review on macOS, head of this branch. I could not build or run any of it: these libraries need the full build, which does not configure on macOS, so everything below comes from reading the code and from the OpenOrbis piglet sample, not from execution.

eglCreateWindowSurface leaks its Vulkan objects on every error path.

Image and Buffer (include/Vulkan.hpp) are plain structs with no destructor; they are released explicitly, as DestroySurfaceNow does with DestroyImage, DestroyBuffer and vkDestroyFramebuffer. EglCreateWindowSurface creates the colour image, the readback buffer and the framebuffer, and only then reaches three statements that throw:

  • Check(device.vkCreateFramebuffer(...), "vkCreateFramebuffer")
  • if (created->videoOut < 0) throw ... sceVideoOutOpen failed
  • if (sceVideoOutRegisterBuffers2(...) < 0) throw ... failed

When one of them throws, std::unique_ptr<WindowSurface> deletes the object without touching the handles, so a VkImage, its VkDeviceMemory and VkImageView, the VkFramebuffer, and the readback VkBuffer with its memory are all lost.

A title that creates a second window surface while the first is alive reaches this: the second sceVideoOutOpen fails, and each retry leaks that set again. EGL allows more than one window surface, so this is not only a malformed-input path.

Releasing what was created before rethrowing, or giving Surface the destructor that DestroySurfaceNow currently open-codes, would close all three at once.

What I checked and found correct, in case it saves someone repeating it:

  • The export surface matches the sample exactly: this PR exports 46 EGL and GLES symbols, and the piglet sample of OpenOrbis samples-elf-llvm-18.zip imports exactly those 46, with nothing missing and nothing unused. I took the import list from relinker --registry on the sample.
  • Describe() bounds its copy with min(item.name.size(), bufferSize - 1) and writes the terminator inside the buffer, so glGetActiveAttrib and glGetActiveUniform do not overrun a caller buffer.
  • lastError is thread_local, as EGL requires, and objectsMutex is held across the surfaces and contexts updates in eglMakeCurrent.

I did not review Context.cpp's GLES state machine beyond the queries above, the glslang path in Program.cpp, or the two companion PRs.

Written with AI assistance. The import cross-check above was run on my own machine; nothing here was executed.

Check(device.vkCreateFramebuffer(device.device, &framebuffer, nullptr, &surface.framebuffer), "vkCreateFramebuffer");

created->videoOut = sceVideoOutOpen(UserServiceUserIdSystem, VideoOutBusTypeMain, 0, nullptr);
if (created->videoOut < 0) throw std::runtime_error("eglCreateWindowSurface: sceVideoOutOpen failed");

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.

This throw, the one below it and the Check on vkCreateFramebuffer all run after the colour image, the readback buffer and the framebuffer exist, and Image/Buffer have no destructor, so unwinding here drops those handles. A second window surface created while the first is open reaches it through sceVideoOutOpen.

@oneandonlydean oneandonlydean self-assigned this Oct 20, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Thanks, this builds and both guest tests pass for us on current main (NVIDIA, Linux).

One change before merge, the same point javierUDP raised: in EglCreateWindowSurface (Egl.cpp), the colour image, readback buffer and framebuffer are created before three calls that can throw (vkCreateFramebuffer at :152, sceVideoOutOpen at :155, sceVideoOutRegisterBuffers2 at :165). WindowSurface has no destructor, so when created goes out of scope on a throw those Vulkan objects leak, and after a sceVideoOutRegisterBuffers2 failure the VideoOut port stays open, so every later attempt fails at sceVideoOutOpen. Could you release them on those paths, for example by giving WindowSurface a destructor that does what DestroySurfaceNow does (and having DestroySurfaceNow rely on it)?

@nikowolf123

Copy link
Copy Markdown
Contributor

There are four more problems besides the eglCreateWindowSurface error-path leak already raised.

1. eglDestroyContext frees none of the context's Vulkan objects. Context has no destructor (Context.hpp#L87). Image, Buffer and Program hold raw handles, so delete target (Egl.cpp#L272) and delete previous in eglMakeCurrent (Egl.cpp#L206) free only the containers. Each destroyed context leaks:

  • its command buffer and the 1x1 incomplete image
  • its 4 MiB vertex and uniform ring chunks
  • its descriptor pools, pipelines and samplers
  • every texture and program still alive

A title that repeats eglCreateContext, eglMakeCurrent, one texmap glDrawArrays, eglSwapBuffers, eglMakeCurrent(EGL_NO_CONTEXT) and eglDestroyContext loses at least 8 MiB of host-visible memory and three VkDeviceMemory allocations per round, until an allocation fails. Device::Submit waits on its fence, so a destructor can free everything directly. vkFreeCommandBuffers and vkDestroyDescriptorPool have to be added to PIGLET_DEVICE_FUNCTIONS first:

Context::~Context() {
    for (auto& [name, program] : programs) program->deletePending = true;
    currentProgram = 0;
    ReleasePrograms();
    for (auto& image : retired) device.DestroyImage(image);
    for (auto& [name, texture] : textures) device.DestroyImage(texture.image);
    device.DestroyImage(incomplete.image);
    for (auto& [key, sampler] : samplers) device.vkDestroySampler(device.device, sampler, nullptr);
    for (const auto pool : pools) device.vkDestroyDescriptorPool(device.device, pool, nullptr);
    for (auto* ring : {&vertexRing, &uniformRing})
        for (auto& chunk : ring->chunks) device.DestroyBuffer(chunk);
    device.vkFreeCommandBuffers(device.device, device.pool, 1, &commands);
}

2. eglDestroySurface frees the display buffers while the last flip may still read them. DestroySurfaceNow closes the port, then delete window frees storage, which holds the two buffers registered with sceVideoOutRegisterBuffers2 (Egl.cpp#L71). eglSwapBuffers waits for flipPendingNum == 0 only before its next copy (Egl.cpp#L243), so the last flip is normally still pending when the surface is destroyed.

On current main, processFlip releases the port's mutex after its vblank wait (VideoOutDriver.cpp#L551-L559). It then presents the buffer (L584), which reads a linear buffer through ReadDisplayBuffer (VulkanDevice.cpp#L3128). close() (L381) only sets closing and does not wait for a presentation that is already past that point. flipPendingNum drops only after the read (L615).

So suppose eglSwapBuffers is followed by eglMakeCurrent(EGL_NO_CONTEXT) and eglDestroySurface, and they land after that vblank but before the presenter has read the frame. The presenter then reads a freed block of about 8 MiB at 1920x1080. If the allocator has already given that block back to the system, CheckRange throws or the read faults, and the presentation thread ends the process. Waiting the way eglSwapBuffers does before closing avoids this, and the same order fits the WindowSurface destructor requested above:

if (window->videoOut >= 0) {
    VideoOutFlipStatus status{};
    while (sceVideoOutGetFlipStatus(window->videoOut, &status) >= 0 && status.flipPendingNum != 0)
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    sceVideoOutClose(window->videoOut);
}

3. A 1x1 texture with a mipmap minifying filter samples as incomplete, including with the default GL_NEAREST_MIPMAP_LINEAR. SampledTexture returns incomplete for any mipmap filter, whatever the texture size (Context.cpp#L293). The OpenGL ES 2.0 glTexParameter page says that a w x h texture has floor(log2(max(w, h))) + 1 mipmap levels, and that level floor(log2(max(w, h))) is the final 1x1 mipmap (es2.0/glTexParameter.xml#L161-L310). It returns (0, 0, 0, 1) only when "there are fewer texture images defined than are needed" (L548-L557). For a 1x1 texture, level 0 is the whole chain, so the texture is complete.

Example: create a white 1x1 GL_RGBA texture with glTexImage2D, call no glTexParameteri, and draw with texmap. OpenGL ES draws white; this draws black. The mipmap frame in guest_piglet uses the 2x2 texture, so it does not cover this case. Fix: change the condition to MipmapFilter(found->second.minFilter) && (found->second.width > 1 || found->second.height > 1).

4. maxLod = 0 makes every sampler use the magnifying filter (Context.cpp#L308). The Vulkan spec note "Mapping of OpenGL to Vulkan Filter Modes" (samplers.adoc#L145-L172) emulates the GL_NEAREST and GL_LINEAR minifying filters with VK_SAMPLER_MIPMAP_MODE_NEAREST, minLod = 0 and maxLod = 0.25. It also says that "using a maxLod of zero would cause magnification to always be performed, and the magFilter to always be used", which only works when the two filters are equal. So GL_TEXTURE_MIN_FILTER is ignored whenever it differs from the magnifying filter.

Example: set GL_TEXTURE_MIN_FILTER to GL_NEAREST, keep the default GL_TEXTURE_MAG_FILTER (GL_LINEAR), and draw a 64x64 checkerboard of single black and white texels into a 16x16 quad. OpenGL ES returns single texels (0 or 255); this blends neighbouring texels into grey. guest_piglet sets both filters to GL_NEAREST, so it cannot catch this. Fix: info.maxLod = 0.25f;.

…sample uses

The OpenOrbis piglet sample loads libScePrecompiledShaders and looks up
"texmap/v_2.vert" and "texmap/f_2.frag" in scePrecompiledShaderEntries,
a table of 0x28-byte entries (name, size at 0x18, data at 0x20) that
ends with a null name, and passes the data to glShaderBinary. The
console table holds Sony's shader binaries, which AnyPS5 cannot ship.

The library now exports the table with AnyPS5's own two shaders under
those names, as GLSL ES 3.10 source behind an "APS5GLSL" line. They are
written from the interface the sample uses: a_vertex with the position
in xy and the texture coordinate in zw, the projection, model-view and
texture-space matrices, the opacity applied to alpha and the sampler.
…glet sample

The OpenOrbis piglet sample renders through libScePigletv2VSH, which
AnyPS5 did not have. It imports scePigletSetConfigurationVSH, 13 EGL 1.4
functions and 33 OpenGL ES 2.0 functions, and passes the shaders it
looks up in libScePrecompiledShaders to glShaderBinary.

The library implements those 47 functions on Vulkan. The shaders are
AnyPS5's GLSL ES source from libScePrecompiledShaders, compiled with
glslang to SPIR-V; the loose uniforms are packed into one uniform buffer
and the samplers are combined image samplers. Draws are recorded into
one render pass per frame with pipelines cached by state, and
eglSwapBuffers copies the frame into the next of two linear VideoOut
buffers once no flip is pending and submits the flip. What the sample
does not use throws.

On MinGW, libc's import library is linked before glslang, and libstdc++
before the import library's trailing copy. The C++ runtime then binds
to libc.prx, and glslang's std::string members, which the import
library lists but libc.prx does not export, bind to libstdc++.

guest_piglet renders five frames into an offscreen surface and checks
their pixels: a 2x2 texture, alpha blending, a texture whose filter
needs missing mipmaps, a viewport, and an RGB texture with 4-byte row
alignment.
…x1 mipmapped textures and the minifying filter

A window surface now releases its framebuffer, color image and readback
buffer in its destructor, so eglCreateWindowSurface no longer leaks them
when vkCreateFramebuffer, sceVideoOutOpen or sceVideoOutRegisterBuffers2
fails; it also waits for the last pending flip before closing the
VideoOut port, so eglDestroySurface cannot free a display buffer the
presenter is still reading. A context frees its command buffer, rings,
descriptor pools, samplers, textures and programs when it is destroyed.
A 1x1 texture is complete with a mipmap minifying filter, and samplers
use maxLod 0.25 so GL_TEXTURE_MIN_FILTER applies when it differs from
the magnifying filter (the Vulkan mapping of the OpenGL filter modes).
@Get-fix
Get-fix force-pushed the ps4/libscepigletv2vsh branch from e983d88 to 95b1f00 Compare October 21, 2026 16:23
@Get-fix

Get-fix commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @oneandonlydean, @nikowolf123 and @javierUDP. All five points are fixed in Get-fix/AnyPS5@95b1f0029, and the branch is rebased onto main cecb540 (#6520 with it, since this one stacks on it):

  1. eglCreateWindowSurface error paths. WindowSurface now has the destructor DestroySurfaceNow used to open-code: it releases the framebuffer, color image and readback buffer, and closes the VideoOut port. A throw from vkCreateFramebuffer, sceVideoOutOpen or sceVideoOutRegisterBuffers2 no longer leaks them, and the port no longer stays open after a failed registration. DestroySurfaceNow now just erases and deletes.
  2. eglDestroyContext. Context has a destructor that releases its programs and pipelines, retired and live textures, the incomplete texture, samplers, descriptor pools, ring chunks and its command buffer (vkDestroyDescriptorPool and vkFreeCommandBuffers added to PIGLET_DEVICE_FUNCTIONS).
  3. eglDestroySurface during the last flip. The surface destructor waits until flipPendingNum is 0 before sceVideoOutClose, so the display buffers are freed only after the presenter has read them.
  4. 1x1 textures with a mipmap filter are complete; only larger textures with a mipmap minifying filter sample as incomplete.
  5. maxLod is 0.25, so GL_TEXTURE_MIN_FILTER applies when it differs from the magnifying filter.

guest_piglet gains a 1x1 white texture drawn with the default GL_NEAREST_MIPMAP_LINEAR (white, not black), a 64x64 checkerboard minified 4:1 with GL_NEAREST and the default GL_LINEAR magnifying filter (only 0 or 255, no grey), and a second context created and destroyed while the first keeps drawing. Reverting fix 4 fails the test at the white texture, and reverting fix 5 at the checkerboard. On main cecb540 with this branch, guest_piglet and guest_precompiled_shaders pass on Windows 11 with an RTX 5060 Ti (610.88), and check_conventions.py passes for both branches. The long debt entry is split into three, each under 1000 characters.

AI-assisted: yes (Claude Code)

🤖 Generated with Claude Code

danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 25, 2026
danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 25, 2026
… fallback pool in HostThreadLocal on Windows

On MinGW the module compiles glslang's PoolAlloc.cpp itself, with DISABLE_THREAD_SUPPORT and its GetThreadPoolAllocator/SetThreadPoolAllocator renamed to unused internal functions, and defines both on a trivially destructible thread_local pointer plus a HostThreadLocal fallback pool. Its object defines every symbol of PoolAlloc.cpp.obj, so ld never takes that member from the shared libglslang.a, whose other members keep their thread support and init lock. prx_thread_local_destructors passes (373 modules), guest_piglet and guest_precompiled_shaders pass.
danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 25, 2026
… when glslang's PoolAlloc.cpp changes or renames its pool accessors

GlslangPoolAllocator.cpp compiles all of PoolAlloc.cpp with DISABLE_THREAD_SUPPORT, so a consistent rename of GetThreadPoolAllocator/SetThreadPoolAllocator or a new THREAD_LOCAL in that file would silently become process-wide. Configure now stops unless the newline-normalized SHA-256 of PoolAlloc.cpp matches the reviewed ba1640446f copy (re-checked on submodule bumps through CMAKE_CONFIGURE_DEPENDS), and -Werror=unused-function turns the never-defined Replaced* declarations into a compile error. The debt entry says so instead of claiming the test catches it. prx_thread_local_destructors, guest_piglet, host_thread_local and guest_precompiled_shaders pass.
oneandonlydean added a commit to oneandonlydean/AnyPS5 that referenced this pull request Oct 27, 2026
…plements

Remove the stub for NID M9RtXpjSYtE, which boykopovar#6521 implements, and correct the
count in the debt entry.
@fogydes

fogydes commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

should-fix

1. Freshness Envelope

  • Head SHA: 95b1f0029a4e0b75e73a87bfcb27d24976df5733
  • Merge-base SHA: cecb540a63f614d2b06cbb557c6d1f6f02475fa3
  • Behind origin/main: 9,066 commits
  • Merge-tree status: exit code 0 (clean merge against origin/main, tree SHA e7b9dd77b3da67a774424a0ee18d9d693ce25063)

2. Findings

  1. [verified] Clean merge tree with origin/main: git merge-tree --write-tree origin/main 95b1f0029a4e0b75e73a87bfcb27d24976df5733 exits with code 0 (no conflicts).
  2. [verified] Conventions clean against merge-base: python tools/check_conventions.py --base cecb540a63f614d2b06cbb557c6d1f6f02475fa3 in an isolated scratch worktree reported 0 findings.
  3. [read-only] Missing checklist line: The PR description omits the required Fixes: line from .github/pull_request_template.md.
  4. [author-reported] Reported test validation in guest_piglet (rendering, blending, EGL state, mipmapping, error paths) and OpenOrbis piglet sample execution at 59.96 FPS on RTX 5060 Ti.

3. Cross-PR Ledger

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

Exports with a name or library/NID already present in main:

  • eglBindAPI (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglChooseConfig (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglCreateContext (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglCreateWindowSurface (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglDestroyContext (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglDestroySurface (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglGetDisplay (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglGetError (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglInitialize (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglMakeCurrent (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglSwapBuffers (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglSwapInterval (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • eglTerminate (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glActiveTexture (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glAttachShader (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glBindTexture (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glBlendFunc (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glClear (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glClearColor (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glCreateProgram (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glCreateShader (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glDeleteProgram (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glDeleteShader (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glDeleteTextures (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glDrawArrays (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glEnable (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glEnableVertexAttribArray (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGenTextures (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGetActiveAttrib (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGetActiveUniform (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGetAttribLocation (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGetError (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGetProgramiv (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGetString (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glGetUniformLocation (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glLinkProgram (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glPixelStorei (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glShaderBinary (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glTexImage2D (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glTexParameteri (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glUniform1f (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glUniform1i (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glUniformMatrix4fv (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glUseProgram (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glVertexAttribPointer (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • glViewport (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)
  • scePigletSetConfigurationVSH (also exported by another library in main: core/libs/prx/libSceGLSlimVSH; may be intentional)

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Hi Get-fix,

Thanks for the EGL/GLES 2 work. We ran this head (95b1f00) merged with current main on Linux and Windows, and two repo checks that landed on main since fail:

  1. public_headers: missing umbrella headers core/libs/prx/libScePigletv2VSH/libScePigletv2VSH.hpp and core/libs/prx/libScePrecompiledShaders/libScePrecompiledShaders.hpp. Each new prx library needs its umbrella header (see any existing core/libs/prx/<lib>/<lib>.hpp).
  2. prx_thread_local_destructors: libScePigletv2VSH.prx: glslang::GetThreadPoolAllocator registers a thread_local destructor. Modules may not register thread_local destructors; HostThreadLocal<T, Storage>() (used in CacheKey.hpp) is the replacement.

Please merge main and check with ctest -R "public_headers|prx_thread_local_destructors".

Thanks.

@github-actions github-actions Bot added review queue Next in the maintainer review queue: checks pass, no open change request, no conflict and removed review queue Next in the maintainer review queue: checks pass, no open change request, no conflict labels Nov 4, 2026

This branch has not been deployed

No deployments
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