swung0x48
3223ecb14e
[Feat] (DirectVulkan): relax fragment precision where the bound formats allow it
...
- WIP, parked: measures 80.9 -> 94.8 fps on Adreno 650 / MC 26.2 (same scene,
device cooled to 38-40C), but is NOT validated. Desktop GLSL carries no
precision qualifiers, so every fragment value reaches the driver as fp32 while
Adreno runs fp16 at twice the rate.
- RelaxTextureDerivedPrecisionPass taints the values a fragment shader derives
from built-in inputs and decorates everything else RelaxedPrecision. The
taint direction matters: whitelisting outward from texture reads captures
nothing, because MC multiplies every texel by an interpolated colour and a UBO
value and one un-relaxed operand vetoes the expression - measured at 80.4 fps,
i.e. no gain, both with and without varyings seeded. Precision-critical
sources are few (gl_FragCoord cannot even hold a 3044-pixel x exactly), so
tainting them and relaxing the rest is what actually pays.
- SPIR-V cannot see the bound formats - sampler2D yields vec4 whether the
texture is RGBA8 or RGBA32F - so the decision is made per draw and passed in
as a compile option, the same shape ExplicitLod0Sampling already uses.
RelaxedFragmentPrecision is only requested when every sampled texture and
every colour attachment is an 8-bit-or-less normalized format, where fp16's
11-bit mantissa already carries the value exactly. Shaderpack HDR gbuffers,
float data textures and 16-bit normalized targets therefore keep full
precision, as do shaders that write gl_FragDepth or gl_SampleMask.
- LocalMultiStoreElim runs first: glslang emits function-local variables, and a
load can never be relaxed, so without SSA promotion the analysis dies at the
first temporary.
- WHY THIS IS PARKED: the retrace correctness gate never ran green. Every
DirectVulkan retrace on Adreno 650 dies with DEVICE_LOST in
UploadDirtyMipLevels on unmodified dev (pre-existing, device-gated), and on
Adreno 830 - where the gate does pass on dev - minecraft-1.21.4-in-world times
out at 900s with this change, which still needs explaining. Do not merge until
that is understood and vanilla plus non-Photon shaderpack cases pass.
(photon-v1.3b is broken on Adreno independently of this work.)
- The /sdcard/MG/exp_relaxed_precision_all and exp_no_relaxed_precision file
toggles are development scaffolding for A/B measurement; they must go before
this ships.
2026-07-29 09:02:00 -04:00
swung0x48
fc4cd980f2
[Fix] (DirectVulkan): bound image mutability so Adreno keeps UBWC compression
...
- Every storage-capable colour texture was created MUTABLE_FORMAT, and Adreno
gives up bandwidth compression on an image that may be viewed as any format in
its compatibility class. MC's main render target therefore ran uncompressed;
in a fill-bound scene that is the whole frame budget. Measured on Adreno 650,
MC 26.2, same scene and camera, device cooled to 38-40C before each run:
65.3 -> 80.9 fps (+23.9%), GPU busy ~93% in both.
- VK_KHR_image_format_list (enabled when present) fixes it without giving up
mutability: VkImageFormatListCreateInfo names the exact formats a view may
use, so the driver can keep the image compressed. The set must be exhaustive
or the result is undefined - for sampled views it is exactly what
ResolveSampledImageViewFormat can return over the three numeric domains.
- glBindImageTexture may name any compatible format, which cannot be enumerated
ahead of time, so a texture bound to an image unit gets no format list. That
is what VK_IMAGE_USAGE_STORAGE_BIT becoming on-demand is for: it makes
"unmarked" mean "will never receive an arbitrary-format storage view", which
is what makes the list sound. Removing STORAGE is worth nothing on its own
(65.4 fps, measured) - only the mutability bound pays.
- MarkStorageImageTexture runs over every collected image-unit texture before
the probe loop in PrepareStorageImageTextures, because that loop stops at the
first texture needing work and would leave the rest unmarked. The mark makes
NeedsStorageImagePreparation report true, which is what ends the render pass,
so the recreate lands outside it.
- storageUsageResolved separates "not upgraded yet" from "this format can never
carry STORAGE", so a format whose optimalTilingFeatures lack STORAGE_IMAGE
cannot ask for a recreate that will never happen. SyncTexture's cross-draw
early-out also has to break on a pending upgrade or the recreate never runs.
- An upgrade recreates the image and carries its contents forward through
PreserveTextureContentsOnRecreate, which submits its own command buffer and
waits. Whatever the frame already recorded into the old image is still
unsubmitted, so that copy would read pre-frame content and this frame's
rendering into the texture would be lost - exactly the render-target-then-
image-unit case. PrepareStorageImageTextures now flushes first; it takes the
FrameData rather than a command buffer because the flush retires the current
one, and drops the sampled-descriptor-set memo that described it.
2026-07-29 07:07:50 -04:00
swung0x48
992d16267c
[Fix] (DirectVulkan): rewrite implicit-LOD fragment samples to explicit LOD 0 when every bound sampler is pinned to a single mip level - Adreno 650 (driver 512.502) reads outside a full-screen colour render target's allocation on its implicit-LOD sampling path and faults the GPU, which killed MC 26.2 on its own blit shader (texture(InSampler, texCoord)) between frames 344-421 on every run; this is the same driver defect the default-framebuffer blit shader already works around with textureLod, but an application's shader cannot be edited, so ForceExplicitLod0SamplePass converts OpImageSample*ImplicitLod to the explicit form at the SPIR-V level under a new CompileOptionBit that is only requested when the rewrite provably cannot move a texel (every sampler binding on a single-level view, no anisotropy, and either a LOD clamp that already pins lambda at 0 or min and mag filters that agree - an explicit LOD 0 always takes the magnification side of the min/mag decision); a single-level view now also clamps its sampler to mipmapMode NEAREST with maxLod min(maxLod, 0.25) rather than 0, since collapsing the clamp would make every fragment magnify and quietly retire the min filter; and the program's backend hash memo grows from one slot to four so a program resolved under two compile-flag sets in the same frame stops re-hashing every stage's SPIR-V once per draw
2026-07-29 03:26:57 -04:00
swung0x48
0ea9e6de5f
[Fix] (DirectVulkan): follow surface resizes instead of rebuilding the swapchain on VK_SUBOPTIMAL_KHR - a per-frame surface-capabilities comparison (ANGLE's model) is now the only thing that schedules a rebuild, so a launcher-side resolution change reaches the swapchain and the compositor scales the smaller image up to the view, while a driver that merely reports the surface as suboptimal can no longer rebuild every frame (each rebuild destroys every pipeline, resets the render-pass manager and reallocates the default framebuffer, which showed as flicker, then corruption, then a crash); the comparison runs in SURFACE space against the extent the live swapchain was created from, since comparing against the swapchain's own quarter-turn-swapped extent reports a difference on every rotated frame
2026-07-28 21:06:57 -04:00
swung0x48
241ed377b4
[Fix] (macOS): harden Cocoa context setup and isolate embedded glslang
2026-07-28 11:54:50 -04:00
swung0x48
bf312a4b67
[Fix] (DirectVulkan): explicit-LOD blit sampling and present-path hardening - the default-framebuffer blit shader now samples with textureLod 0 (a blit reads exactly the selected level; Adreno 650's implicit-LOD path reads past a single-mip UBWC render target's allocation despite maxLod=0, page-faulting the GPU on MC 26.2's second startup frame once the neighbouring startup staging memory is returned - the invalidated context then failed the next Present submit with EDEADLK/DEVICE_LOST), TransitionToPresent appends the present barrier into the frame's open recording instead of silently dropping it whenever anything was recorded (frames without a default-FBO render pass presented images stuck in their acquired layout), VK_SUBOPTIMAL_KHR acquires are treated as the success they are (image acquired, semaphore signal armed - the early return skipped the fence reset and consumed-flag clear, and callers re-acquired on the same binary semaphore; rebuilds now defer to after the signal is consumed), and validation builds report through VK_EXT_debug_report when VK_EXT_debug_utils is absent instead of aborting instance creation
2026-07-28 06:00:20 -04:00
swung0x48
56b31a9587
[Fix] (FastSTL): bump submodule for the erase(iterator) double-advance fix and add erase-while-iterating regression tests - the old semantics skipped one live element per erase and ran past end() when erasing the highest occupied bucket, sending the new mass pipeline-cache eviction sweeps off the bucket array (device crash on first eviction during world load: garbage handles fed to vkDestroyPipeline)
2026-07-27 23:50:25 -04:00
swung0x48
8a0a8a0274
[Fix] (DirectVulkan): harden the leak-fix round after adversarial review - pipeline memo now drops at every command-buffer boundary (a flush-loop-memoized pipeline could age out and be destroyed while its submission was in flight), mid-frame drains no longer rewind the arena or advance the cache-aging clocks in presenting apps (gated to every 8th drain since the last Present, so readback/fence-heavy frames neither churn conversions nor shrink the 1024-boundary retire window), render-pass eviction notifies the pipeline cache once per sweep batch instead of once per dying pass, descriptor pools use FREE_DESCRIPTOR_SET_BIT so a destroyed layout's cached sets are freed back and credited instead of abandoning pool slots (the live-layout age sweep that could orphan slots is removed - layout destruction is the sole purge path), and renderbuffer respecify parks the old backing for aged destruction instead of destroying it while possibly in flight
2026-07-27 22:51:26 -04:00
swung0x48
d076c29146
[Fix] (DirectVulkan): bound the vertex-input and sampler caches and sweep undeleted GL syncs - both caches age out entries idle >1024 frame boundaries (animated LOD bias no longer mints a VkSampler per float value, buffer/VAO churn no longer grows the vertex-input map for the whole session), and library teardown drains the live-sync registry exactly as glDeleteSync would since GL requires syncs to die with their context
2026-07-27 22:16:16 -04:00
swung0x48
930a607bdf
[Fix] (DirectVulkan): make texture/renderbuffer GC reach every dead resource - name-deleted textures register via weak_from_this so first-sync-after-delete can no longer orphan a TextureResource, an orphan sweep makes GC authoritative over the resource map, dead-texture pruning moves to a frame-boundary gate (64 frames) so churn through clears/readbacks reclaims without draws, and dead renderbuffers age past frames-in-flight before their VkImage/view is destroyed instead of leaking until shutdown (or being freed while in flight)
2026-07-27 22:16:15 -04:00
swung0x48
34685b4bb0
[Fix] (DirectVulkan): age-based eviction for the content-addressed cache family - ProgramFactory entries (shader modules/layouts), PipelineFactory graphics pipelines, compute pipelines and per-layout descriptor-set tracking now retire after ~1024 idle frame boundaries (render-pass-manager sweep precedent), render-pass eviction purges pipelines hashed on the dying handle (closes a handle-recycling stale-pipeline hazard), and the program reflection cache is lifetime-id-keyed and cleared at EGL teardown - shader/program churn no longer grows Vulkan objects without bound
2026-07-27 22:05:25 -04:00
swung0x48
c540fb88ee
[Fix] (DirectVulkan): drain frame transients on present-less paths - readback waits, suspended presentation, blocking sync waits and flush completion polls now run Present's per-frame drains (deferred buffer/texture releases, transient arena rewind, descriptor cursors, retired command buffers, conversion caches) whenever every submission is provably complete, so offscreen/minimized workloads stay bounded; never blocks, frames-in-flight overlap untouched
2026-07-27 21:45:21 -04:00
swung0x48
6ae3245a0d
[Test] (CTS): raise the no-output abort threshold - consecutive instant-crash cases are real progress once device liveness is confirmed
2026-07-26 19:23:05 -04:00
swung0x48
7e048fc2bf
[Fix] (DirectVulkan): map RGB10_A2(UI) to A2B10G10R10 - GL 2_10_10_10_REV puts R in bits 0-9 so the A2R10G10B10 mapping silently swapped R/B on upload; also decode both 1010102 variants in readback
2026-07-26 19:13:46 -04:00
swung0x48
83cdfd6bdd
[Fix] (DirectVulkan): GetTexImage reads all 3D slices/array layers with PACK_IMAGE_HEIGHT/SKIP_IMAGES semantics, and sRGB readback returns raw sRGB-encoded bytes instead of linearizing
2026-07-26 18:30:43 -04:00
swung0x48
1c76f886cf
[Fix] (DirectVulkan): back legacy low-bit formats (RGB565/RGB5A1/RGBA4/R3G3B2/RGB4/RGBA2/RGB10/12) with their UNorm8/16 canonical shadow layouts and add capability fallbacks - they mapped to VK_FORMAT_UNDEFINED and crashed or wedged the GPU on upload; also admit 2DMSArray/CubeMap/3D color attachment targets in the render pass
2026-07-26 18:30:42 -04:00
swung0x48
a2e109beff
[Fix] (DirectVulkan): general (format,type) readback conversion - hoist the CTS-verified StoreWideRowsToClient into shared ReadbackImpl and decode any color VkFormat to wide RGBA rows; readback previously supported only RGB/BGR/RGBA/BGRA x UNSIGNED_BYTE/FLOAT and silently returned zeros for everything else
2026-07-26 18:30:41 -04:00
swung0x48
63f0756644
[Fix] (DirectVulkan): support UBO instance arrays as arrayed descriptors - uniform Block{...}b[N] reflected as one binding with descriptorCount=N, per-element GL block mapping, per-element buffer infos and dynamic offsets; non-UBO descriptor arrays now fail program creation cleanly instead of continuing corrupt
2026-07-26 18:30:41 -04:00
swung0x48
450215d12c
[Fix] (DirectVulkan): implement color renderbuffer attachments - render pass/pipeline/blit/copy/readback/clear paths treated color renderbuffers as absent (writes masked to VK_ATTACHMENT_UNUSED, glClear dropped, readback zeros)
2026-07-26 18:30:40 -04:00
swung0x48
3a9e520170
[Test] (CTS): isolate the DirectVulkan renderbuffer-FBO readback defect so the rest of KHR-GL33 can be measured
2026-07-26 18:30:39 -04:00
swung0x48
d2996ba1cf
[Test] (CTS): run VK-GL-CTS KHR-GL33 against MobileGL on Android via a standalone glcts binary
2026-07-26 18:30:39 -04:00
swung0x48
c8632dfefe
[Test] (piglit-android): add on-device piglit harness for MobileGL - patched waffle (WAFFLE_EGL_LIBRARY/WAFFLE_GL_LIBRARY overrides so waffle drives libMobileGL.so directly, AImageReader-backed windows for DirectVulkan since Android ICDs lack VK_EXT_headless_surface, WAFFLE_FORCE_GL_CONTEXT_VERSION to upgrade piglit's low compat context requests to 3.3 core, meson cross fixes) and patched piglit (Android platform support, EGL support decoupled from the X11-dependent EGL tests, and a dispatch-init fix: the waffle resolvers were never installed because gl_fw is NULL during framework construction, so gl* silently bound to the system driver via the DT_NEEDED libEGL's eglGetProcAddress), plus the adb chunked runner with PIGLIT-result parsing, a results comparator, cross-file examples, and the piglit-on-android skill
2026-07-26 11:57:11 -04:00
swung0x48
b8a8a660e1
[Refactor] (Lifecycle): own MobileGL's lifecycle from the EGL layer instead of ELF static ctor/dtor - the first EGL/WGL entry point lazily initializes via a thread-safe, re-init-capable EnsureInitialized (AutoInit is gone), the last eglTerminate with no initialized display and nothing current tears the whole library down deterministically inside the EGL lifecycle, and the global singletons move to leak-at-exit heap storage so process exit runs no backend destructors at all (AutoDestroy and the Windows DllMain abandon hook are gone); fixes the exit-time SIGABRT from undefined static-destruction order - the DirectGLES buffer-pool mutex abort on Android clean exits, and the pre-existing macOS QueryTest/ProgramTest 'Subprocess aborted' gtest failures now pass (ctest 411/411)
2026-07-26 10:59:14 -04:00
swung0x48
7ab83861ca
[Fix] (DirectVulkan): suspend presentation while the window is zero-area - a minimized window's out-of-date swapchain used to keep Present submitting on a signaled fence and presenting never-acquired images (adversarial review); also drop logging from the process-detach abandon path
2026-07-26 07:59:40 -04:00
swung0x48
eaeba556a3
[Test] (WGL): add manual Windows smoke tests - hand-rolled WGL bootstrap and GLFW-driven variant covering the zero-area helper-window path
2026-07-26 07:21:36 -04:00
swung0x48
72fa1221a5
[Fix] (DirectVulkan): survive zero-area windows at renderer init - skip the eager first acquire when RecreateSwapchain's minimize guard left no swapchain (GLFW's hidden helper window), and let Present bring the swapchain up once the window has real size
2026-07-26 07:16:11 -04:00
swung0x48
c4254c4bbd
[Feat] (WGL): add Windows host layer - drop-in opengl32.dll with WGL over EGLImpl, Win32 window backend plumbing for both backends, ANGLE loader path, and leak-at-exit process teardown
2026-07-26 06:46:29 -04:00
swung0x48
199164c2e0
[Perf] (DirectGLES): route the per-upload GL_PIXEL_UNPACK_BUFFER unbinds through the unpack binding cache - the six texture-upload sites re-issued glBindBuffer(UNPACK, 0) on every upload; with the resting-0 shadow they now no-op after the first
2026-07-21 19:54:55 -04:00
swung0x48
e87063e90c
[Fix] (DirectGLES): route default-framebuffer binds through the FBO-binding shadow - the raw glBindFramebuffer(0) in BindCurrentFBO/SyncAndBindFramebufferObject left the shadow claiming the previous user FBO, false-skipping its next re-bind and letting scoped guards restore a stale binding (caught by adversarial review); also scrub buffer-binding shadows when VAO client-attribute staging buffers are deleted, include cube-map arrays in the pack-image-params gate, and make the delete-recording test hook assertion-unwind safe
2026-07-21 19:54:54 -04:00
swung0x48
122da27249
[Fix] (DirectGLES): overhaul readback/copy/blit driver-state handling with shadow-backed RAII guards - pixel-PACK/UNPACK PBO binding caches resting at 0 (the old bind-then-query 'restore' left the user PBO bound forever, capturing later client-memory readbacks), a PACK pixel-store shadow replacing per-readback glGetIntegerv syncs, a driver FBO-binding shadow behind all scoped binders (per-instance prev slots, nest-safe), scratch-FBO attachment shadows that detach cross-aspect residue exactly when present (depth CopyTex* attachments used to wedge later GetTexImage color reads and vice versa), scissor guards around emulation blits (app scissor clipped depth copies), stale-driver-error drains before single-shot glGetError consumers (fallbacks silently dropped readbacks / GenerateMipmap raised phantom app errors in production builds), ClearBufferiv missing BindCurrentFBO(Draw), cube-face glBindTexture INVALID_ENUM cache poisoning, per-slice GL_PACK_IMAGE_HEIGHT/SKIP_IMAGES semantics on 3D GetTexImage, backend texture ids deleted on wrapper destruction with cache/scratch-FBO scrubs (ids used to leak for the context lifetime and dangling cache pointers could false-skip binds), and context-death/MakeCurrent invalidation for all new shadows; regression tests drive the shadows against a recording mock GLES table
2026-07-21 19:54:54 -04:00
swung0x48
bc2d698b3e
[Fix] (DirectGLES): apply the read buffer when one FBO is bound as both draw and read
...
- SyncCurrentFBO skips the READ-target pass when the same GL FBO is bound as
both draw and read (the common GL_FRAMEBUFFER case), but the read buffer
(glReadBuffer) is only applied inside SyncToBackend's READ path — so the skip
silently dropped every glReadBuffer change, leaving the backend read buffer
stuck at COLOR_ATTACHMENT0.
- Extract the read-buffer application into BackendFramebufferObject::
SyncReadBufferToBackend and invoke it from the skip branch (target == Read)
as well as from SyncToBackend, so reads always target the right attachment.
- Bind the backend FBO as READ inside the helper before glReadBuffer, since the
skip path only bound it as DRAW.
- Fixes KHR-GL3x.draw_buffers.draw_buffers_1 (reading COLOR_ATTACHMENT1 while
the FBO stays GL_FRAMEBUFFER-bound returned attachment 0's value); the render
was already correct, only the readback resolved the wrong attachment.
2026-07-21 12:18:55 -04:00
swung0x48
3049c4b82b
[Fix] (ShaderTranspiler): stop blanking block comments in the source handed to glslang
...
- BlankBlockComments replaced comment chars with spaces but preserved interior newlines, so a block comment spanning a newline inside a #define truncated the macro body (VALUE became empty)
- glslang has a conformant preprocessor and collapses a block comment to one space across newlines, so the delivered source now keeps comments intact and lets glslang handle them
- Fixes KHR-GL3x.shaders.preprocessor multiline_comment_define / redefine_object_multiline_comment / function_redefinition_3 (6 cases, both devices)
- FilterUnsupportedGpuShaderInt64 relied on the blanking to skip commented-out #extension lines; it now masks comments locally (MaskCommentsAndQuotedText) like the sibling passes, collecting edits and applying them back-to-front
- conditional_inclusion.basic_2 (defined() via macro expansion) stays failing by design: glslang rejects it as UB and working around it would mean re-running preprocessing MobileGL defers to glslang
2026-07-21 05:27:01 -04:00
swung0x48
2b3850b76b
[Fix] (DirectGLES): upload RGB565/RGB5_A1 shadow data as packed 16-bit types
...
- The 8-bit unorm shadow was uploaded as GL_UNSIGNED_BYTE, leaving the 8->5/6-bit requantization to the driver
- That rounding direction is implementation-defined: Adreno rounds to nearest (lossless round trip), Mali floors
- On Mali mid-range texels drifted one 5-bit step down, failing all 20 KHR-GL33.pixelstoragemodes.teximage3d rgb565/rgb5a1 cases (eps 1/32); layers with exact values (0.125/0.25/1.0-ish) passed, matching the observed 0,1,7-valid pattern
- PreparePackedNormUpload repacks shadow rows to GL_UNSIGNED_SHORT_5_6_5 / 5_5_5_1 with round-to-nearest, which exactly recovers the original 5/6-bit values (the shadow expansion is injective), so the driver stores them verbatim
- Idempotent across each region's level loop (glType is shared); RGBA4 exempt since its 8-bit expansion (v*17) is exact under either rounding
- Wired at all four SyncMipmapsToBackend upload regions (append-mipmaps, immutable TexSubImage, mutable full, dirty-level update)
2026-07-21 04:30:46 -04:00
swung0x48
2a0ae743a0
[Fix] (DirectGLES): glFinish before the glGetTexImage temp-FBO readback
...
- Mali (tile-based) does not resolve a texture's render into memory when it is read back through a different (temp) FBO than the one it was rendered with
- The cross-FBO glReadPixels raced the deferred tile resolve and returned pre-render clear contents
- Distinct render targets read back byte-identical, so KHR-GLxx.glsl_noperspective failed on Mali-G715 (all four programs read as the clear colour)
- glGetTexImage is already a CPU/GPU sync point so the extra drain is negligible; Adreno resolves eagerly and was unaffected
2026-07-21 03:34:33 -04:00
swung0x48
6839219c10
[Fix] (GLImpl): report GL_NO_ERROR from glGetGraphicsResetStatus
...
- The generic export stub returned (GLenum)1; dEQP reads any non-zero status as a lost device
- It is polled after every case (gl3cTestPackages.cpp:121) and sets QP_TEST_RESULT_DEVICE_LOST
- Under the default --deqp-terminate-on-device-lost=enable that tears the whole CTS run down
- MobileGL tracks no GPU resets, so GL_NO_ERROR ("no reset detected") is the honest, spec-correct answer
- Routed through GLImpl::GetGraphicsResetStatus like every other entry point, no inline body in Definitions.cpp
2026-07-21 02:40:15 -04:00
swung0x48
52ddb440ca
[Feat] (SelfTest/DriverPost): add a noperspective correctness check to the GLES POST - render a strong-perspective quad and read the centre texel to verify the varying interpolates screen-linear (not perspective-correct), carried through the native GL_NV_shader_noperspective_interpolation path when present or MobileGL's exact gl_Position.w/gl_FragCoord.w emulation when absent. PASS = native and correct; WARN = emulated and correct (the fallback path shipping packs hit on such devices); FAIL = interpolation wrong/perspective-correct, or the program will not build. The ESSL header matches the device version because noperspective is rejected at #version 300 es on some drivers even with the extension enabled
2026-07-21 02:09:17 -04:00
swung0x48
79feeffd25
[Feat] (ShaderTranspiler, DirectGLES): emulate noperspective on GLES devices lacking GL_NV_shader_noperspective_interpolation - EmulateNoPerspectivePass pre-multiplies each NoPerspective output by gl_Position.w in the vertex stage and recovers each input via gl_FragCoord.w in the fragment stage (exact screen-linear L = P(a*w)*gl_FragCoord.w, handling whole-variable and component/access-chain reads, scalar and vector varyings), forces highp on emulated varyings, and strips what it cannot emulate; replaces the smooth-strip fallback so no NV extension is ever required. Restricts the vertex pre-multiply to the entry function so a non-inlined helper cannot double-scale
2026-07-20 23:48:48 -04:00
swung0x48
202037b5a3
[Fix] (DirectVulkan): shrink the blended depth-write quirk to MIN/MAX extremum blends only - a fixture-wide trace sweep showed the additive ONE+ONE arm never fires on the 26.3 OIT chain (its accumulation passes disable depth writes themselves) and only hit unrelated additive glow content; also fail reflection toward the gl_FragDepth exemption and zero phantom default-FBO blend slots so stale indexed state cannot trigger the strip
2026-07-20 23:39:28 -04:00
swung0x48
bce9c48c8e
[Feat] (ShaderTranspiler, DirectGLES): support noperspective conformantly instead of stripping it - let the qualifier reach glslang as the core SPIR-V NoPerspective decoration (native on DirectVulkan; SPIRV-Cross emits ESSL noperspective + GL_NV_shader_noperspective_interpolation on DirectGLES), and for GLES devices lacking that extension add StripNoPerspectivePass to drop the decoration and fall back to smooth; the old naked substring erase discarded the interpolation shader packs need and mangled identifiers containing the word
2026-07-20 22:59:43 -04:00
swung0x48
b6a7807a3a
[Fix] (MG_Util/ShaderTranspiler): reject malformed #version directives instead of legalizing them - an unrecognized version number (329/331), a bad profile keyword, a float or trailing token used to be rewritten to "#version 330 core" (or rescued to 460 by the retry); now InspectShaderLanguage marks such directives invalid so NormalizeVersionDirective and RetargetLegacyVersionDirectiveTo460 leave them for glslang to reject, while every valid version still normalizes as before
2026-07-20 22:03:36 -04:00
swung0x48
48ba622387
[Fix] (MG_Util/ShaderTranspiler): keep #line directives instead of deleting them, dropping only the GLSL-illegal quoted filename and the ones that precede #version, so __LINE__ and compiler diagnostics follow the application's own numbering
2026-07-20 21:06:38 -04:00
swung0x48
05260d1262
[Fix] (MG_Util/ShaderTranspiler): blank block comments lexically instead of erasing them - a '//*** banner ***' line opened a comment the old scanner never closed, so it deleted the rest of the shader, and a commented-out builtin definition renamed every genuine call to a name nothing defines
2026-07-20 21:06:37 -04:00
swung0x48
6eb5ff51c5
[Fix] (MG_Impl/GLImpl): reject the RGTC internal formats on 3D texture targets - RGTC compresses 4x4 blocks of a 2D image and has no 3D form, and the check must run on the raw enum because RGTC now resolves to plain R8/RG8 storage
2026-07-20 21:05:57 -04:00
swung0x48
e526f8e8ac
[Fix] (MG_Util/Converters): resolve the GL_COMPRESSED_* internal formats to the uncompressed storage that backs them instead of rejecting them as unknown - GL prescribes this base-format fallback for the six generic formats, and RGTC stores uncompressed because ES exposes no compressor
2026-07-20 21:05:57 -04:00
swung0x48
e724e88eec
[Fix] (MG_State, MG_Impl/GLImpl): allocating a mipmap level no longer truncates the chain above it - AllocateLevel now only grows and the callers that genuinely redefine the whole level set (glTexStorage*, mip regeneration, multisample storage, level-0 respecification) drop the tail explicitly
2026-07-20 21:02:54 -04:00
swung0x48
3b175fb88a
[Fix] (MG_Impl/GLImpl): a multisample sample count above the format's maximum is INVALID_OPERATION, not INVALID_VALUE - matching both the spec and the native Adreno driver
2026-07-20 21:02:53 -04:00
swung0x48
b5a4e7075a
[Fix] (MG_Impl/GLImpl): record a GL error from the unimplemented compressed texture entry points instead of throwing - a C++ exception unwinding through the C GL ABI hard-crashes any caller, and glGetCompressedTexImage reported success while writing nothing
2026-07-20 21:02:53 -04:00
swung0x48
520c2b6750
[Fix] (MG_Backend/DirectGLES): sync GL_TEXTURE_SWIZZLE_* on multisample targets - the early return meant to skip the sampler-only parameters dropped every swizzle write, which the frontend already treats as legal on those targets
2026-07-20 21:02:52 -04:00
swung0x48
57cc652b1d
[Fix] (MG_Impl/GLImpl): glIsTransformFeedback reports GL_FALSE instead of claiming every name it is handed is a live transform feedback object
2026-07-20 21:02:52 -04:00
swung0x48
65ea54da9e
[Refactor] (ShaderTranspiler, DirectVulkan): replace the hand-rolled SPIR-V word walkers with a DecoratePositionInvariantPass and SPIRV-Reflect-based InstanceIndex detection
2026-07-20 08:35:00 -04:00
swung0x48
c81dd04f08
[Test] (CI, trace_replay): force the blended depth-write quirk on the Linux DirectVulkan OIT retrace lane and tighten that case's SSIM threshold to 0.995
2026-07-20 07:39:25 -04:00
swung0x48
c158bfa584
[Fix] (DirectVulkan): narrow the blended depth-write quirk to order-independent accumulation blends, exempting sorted-transparency, gl_FragDepth writers and fully masked attachments
2026-07-20 07:39:25 -04:00
swung0x48
f9f455144c
[Refactor] (MG_Config, DirectVulkan): route the blended depth-write quirk through the FeaturesTable as MOBILEGL_MAGMA_DISABLE_BLENDED_DEPTH_WRITE instead of an ad-hoc getenv
2026-07-20 04:37:23 -04:00
swung0x48
64e4840de2
[Fix] (DirectVulkan): fall back to immutable images when the mutable probe fails, gate robustBufferAccess behind MOBILEGL_DISABLE_ROBUST_BUFFER_ACCESS, decode R32/RG32/R16-class readback formats, and warn when shaderStorageImage*WithoutFormat is unavailable
2026-07-20 02:36:26 -04:00
swung0x48
bf7b5755cc
[Refactor] (ShaderTranspiler, MG_Backend, MG_Util): gate the subgroup prefix-scan rewrite behind a generic device-quirk registry with GPU vendor detection and MOBILEGL_QUIRK_SUBGROUP_PREFIX_SCAN override, warn on template mismatch, and block ARB/NV subgroup spellings
2026-07-20 02:36:26 -04:00
swung0x48
293f64b3c2
[Fix] (MG_Impl, DirectGLES): correct ARB_clear_texture error codes, reject cube maps in CopyTextureSubImage2D, advertise the extension on Espryt, and pin the error contracts with tests
2026-07-20 02:36:25 -04:00
swung0x48
f0cc07c937
[Perf] (DirectVulkan): bound vertex-stream conversion by the draw's real fetch range, reuse cached prefixes, pin cached source buffers, and stop repacking client arrays for pointer alignment
2026-07-20 02:36:25 -04:00
swung0x48
4658536652
[Perf] (DirectVulkan): keep the render pass alive for steady-state storage-image draws and skip storage-image collection for programs without them
2026-07-20 02:36:24 -04:00
swung0x48
04b4627c65
[Fix] (DirectVulkan): pass depth/stencil formats through sampled-view resolution so D24S8/D32FS8 samplers stop dropping draws, and memoize per-binding view-format resolution
2026-07-20 02:36:24 -04:00
swung0x48
68e13705c8
[Fix] (MG_Backend/DirectVulkan, ShaderTranspiler, MG_Test, TraceReplay): make iterationRP retrace pass on 64-lane Vulkan devices with subgroup-width emulation and format-aware readback
2026-07-20 02:36:23 -04:00
swung0x48
e5388c0e7e
[Fix] (MG_Backend, MG_Impl, ShaderTranspiler, MG_Test): support iterationRP custom images and storage format reinterpretation
2026-07-20 02:35:30 -04:00
swung0x48
8bc4808b1a
[Test] (TraceReplay): match the iterationRP fixture name published on the mirror
2026-07-19 23:09:29 -04:00
swung0x48
5d8a5387e2
[Test] (TraceReplay): try the hit.moe mirror before miawa and Git LFS
2026-07-19 22:29:55 -04:00
swung0x48
aa2184e47a
[Test] (TraceReplay): register iterationRP in-world fixture (non-CI, fixture files pending LFS)
2026-07-19 21:39:06 -04:00
swung0x48
9152a4a4bc
[Test] (TraceReplay): enable improved-transparency fixture in CI and drop unneeded coherent_as_flush
2026-07-19 07:35:34 -04:00
swung0x48
1963b427db
[Refactor] (TraceReplay): reorganize trace skills into uniform packages with bundled scripts
2026-07-19 07:00:56 -04:00
swung0x48
f3def150e7
[Fix] (DirectVulkan): suppress blended depth writes on Qualcomm and mark gl_Position invariant to fix MC 26.3 OIT cloud flicker
2026-07-19 05:47:23 -04:00
swung0x48
fc0688c223
[Fix] (CI): stabilize Android retrace jobs
2026-07-18 19:52:04 -04:00
swung0x48
626c7f26fd
[Test] (CMake, CI): enable top-level testing and label tests (unit/benchmark/integration) so ctest runs from the build root
2026-07-18 11:37:56 -04:00
swung0x48
1d947d934b
[Feat] (TraceReplay): add RenderDoc Android capture tools
2026-07-18 11:25:07 -04:00
swung0x48
4203837648
[Feat] (trace-replay): register improved transparency fixture
2026-07-18 07:28:55 -04:00
swung0x48
f5cba4c2f1
[Docs] (trace-replay): unify Android trace runner docs
2026-07-18 07:06:56 -04:00
swung0x48
c2a1db3fcb
[Feat] (trace-replay): add improved transparency fixture
2026-07-18 05:34:01 -04:00
swung0x48
594916850f
[Fix] (MG_State, MG_Backend/DirectVulkan): bump the texture bind generation when a context default texture crosses the undefined<->defined boundary so cached sampled sets re-resolve, and collect the fallback texture into the sampled set so its first use transitions outside the render pass
2026-07-17 22:33:31 -04:00
swung0x48
c718d6bad8
[Fix] (MG_Test/Backend/DirectVulkan): link the whole MobileGL_s archive on MSVC so dllimport-declared gl*/egl* references resolve against the in-library entry points
2026-07-17 21:32:17 -04:00
swung0x48
abfda60ff1
[Perf] (MG_Backend/DirectGLES): check the unbind cache before activating the texture unit so the bind-0 sweep stops issuing redundant glActiveTexture per draw
2026-07-17 21:32:16 -04:00
swung0x48
92cced9bcc
[Fix] (MG_State, MG_Impl, MG_Test): enforce strict GL 3.3 core rules only on contexts that explicitly request a core profile - texture deleted-name reservation keep and VAO-0 draws relax otherwise or under MOBILEGL_RELAXED_SEMANTICS, and GL_CONTEXT_PROFILE_MASK reports the requested profile
2026-07-17 21:32:16 -04:00
swung0x48
1929a7c546
[Fix] (MG_State, MG_Backend/DirectGLES): preserve legacy texture reuse and clear default backend bindings - keep generated-but-unbound names alive for Minecraft 1.7.10 atlas uploads, synchronize bind-0 to native GLES without 1D/2D alias churn, and cover both paths with BGRA sub-image and binding-cache regressions
2026-07-17 21:32:15 -04:00
swung0x48
df7f5a369d
[Fix] (MG_Backend/DirectVulkan): render passes had zero subpass dependencies and same-layout transitions emit no barrier, so tilers could race tile loads against prior passes' stores (flickering artifacts in multi-pass chains like MC 26.3 OIT); add conservative external dependencies both ways
2026-07-17 21:03:52 -04:00
swung0x48
0de9861da4
[Fix] (MG_Backend/DirectVulkan): render-pass cache grew unbounded; age entries per present and evict after 1024 unused frames
2026-07-17 20:03:54 -04:00
swung0x48
6b223e4d23
[Fix] (MG_Backend/DirectVulkan): blendEnable was baked into pipelines without checking VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; disable blending on formats that lack it
2026-07-17 20:03:53 -04:00
swung0x48
48568cdb89
[Fix] (MG_Backend/DirectVulkan): deferred glClear/glClearBuffer ignored color/depth/stencil write masks; gate the queued planes like the scissored path
2026-07-17 20:03:53 -04:00
swung0x48
8d83dedc0f
[Fix] (MG_Backend/DirectVulkan): pending deferred clears outlived blit/copy writes into the same texture and later stomped them (OIT's cloud_depth copy was erased by its own earlier queued clear); materialize destination pending clears before blit/copy writes
2026-07-17 19:24:55 -04:00
swung0x48
a25d8ee0e7
[Fix] (MG_Backend/DirectGLES): GLES clamps glClearColor to [0,1], zeroing the -FLT_MAX MAX-blend identity; route out-of-range color clears through glClearBufferfv
2026-07-17 11:45:55 -04:00
swung0x48
c30bd0fabb
[Fix] (MG_Backend/DirectGLES, MG_Impl/GLImpl): draw/read-buffer state could land on the wrong FBO (glDrawBuffer's static-array latch; SyncToBackend emitting glDrawBuffers/glReadBuffer for the non-bound target; no resync on bound-FBO attachment/drawbuffer edits) leaving MC 26.3's OIT color clears as no-ops; apply per bound target and track the FBO object version
2026-07-17 11:45:54 -04:00
swung0x48
c9fbf79d6a
[Fix] (MG_Backend/DirectGLES): blend equations were never synced to the driver (OIT's GL_MAX ran as ADD); diff and emit glBlendEquationSeparate(i) alongside the factor sync
2026-07-17 11:45:53 -04:00
swung0x48
f39e8738da
Merge origin/dev (readback overhaul c6d22e6e) into default-texture-objects - true per-target default texture objects supersede the readback branch texture-0 silent no-ops: removed the null-slot early-outs in TexImage1D/2D/3D(Multisample) and TexBuffer plus the DefaultTextureOperationsAreSilentNoOps test so name-0 operations actually (re)specify the default objects; deduped the shared state-reset fixes, keeping upstream std::clamp for GL_MAX_UNIFORM_BUFFER_BINDINGS, the Int-typed ActiveTexture combined-units range check, renderbuffer name-0 unbind, and vertex-attrib-0 current-value writes with the attrib-0 round-trip test
2026-07-16 23:50:47 -04:00
swung0x48
c6d22e6ece
Merge branch 'dev' of https://github.com/MobileGL-Dev/MobileGL into dev
2026-07-16 23:38:48 -04:00
swung0x48
981f10e4da
[Fix] (MG_Impl/GLImpl): unblock the non-texture sections of GL CTS per-case state reset - clamp advertised GL_MAX_UNIFORM_BUFFER_BINDINGS to the state layer indexed-binding capacity (glBindBufferBase rejected indices past it), let glBindRenderbuffer(0) unbind without recording INVALID_OPERATION (name 0 must never reach the name-table lookup), and allow writes to generic vertex attribute 0 current value (core GL has no attribute-0 restriction; gluStateReset writes vertexAttrib4f(0,...) after every case) - with these plus the default-texture work, multi-case glcts batches complete in one process instead of aborting after the first case
2026-07-16 23:36:58 -04:00
swung0x48
076cd0d19d
[Feat] (MG_State, MG_Impl/GLImpl): per-target default texture objects (name 0) - binding 0 binds a real per-context default object (the initial binding of every unit/target slot, rebound on delete of a bound texture), so glTexImage*/glTexParameter*/glGetTex* on it work like any texture while glIsTexture(0)/Gen/Delete keep excluding it and TexStorage* rejects it per spec; backends skip image-less defaults as cheaply as the old null slots (DirectGLES per-draw sync/bind loops, DirectVulkan sampler-fallback resolve); also accept the full advertised GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS range in glActiveTexture, allow zero-layer TexImage3DMultisample, and let glTexBuffer(buffer=0) detach - the texture section of GL CTS per-case state reset (gluStateReset) now runs clean
2026-07-16 23:36:43 -04:00
swung0x48
5cd82f2002
Merge origin/dev ( efd7b473) into readback overhaul - unify DirectGLES 2D-array target support under MapToBackendTextureTarget, keep canonical UNorm8 shadows for RGBA4/RGB565 (supersedes packed-word transfer types; GL_RGB565 aliases RGB5), keep upstream GLSL 330 normalization, anisotropy params, error-count semantics and VK clear/scissor fixes
2026-07-16 23:17:37 -04:00
swung0x48
d4922cb0fb
[Fix] (MG_Backend, MG_Impl/GLImpl, MG_Util): make anisotropic filtering actually reachable - advertise GL_EXT/ARB_texture_filter_anisotropic only where the host driver or the samplerAnisotropy device feature supports it, answer GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT from the backend limit, and honor the sampler state on DirectVulkan (feature enable, limit clamp, LINEAR-only gate, resolved value in the sampler cache key)
2026-07-16 22:59:11 -04:00
swung0x48
870d882fef
[Fix] (MG_Backend/DirectGLES, MG_Impl/GLImpl, MG_Util): GL CTS packed_pixels + texture_swizzle readback overhaul - canonical shadow layouts for legacy sized/unsized/packed internal formats (RGB5->RGB565, RGB10/12->RGB16, RGBA2->RGBA4, RGB10_A2(UI)/RGB9_E5/R11F_G11F_B10F packed-word shadows with per-texel encode/decode incl. 5_9_9_9_REV and 10F_11F_11F_REV client types), GL_UNSIGNED_INT_10_10_10_2 pixel type mapping, conversion-first GetTexImage with CPU-shadow fallback for non-attachable formats and stale-temp-FBO detach, narrow implementation read pairs + SNORM read candidates + 2_10_10_10_REV wide-read decode with RGBA expansion, PACK image/skip and SWAP_BYTES honored on the CPU repack (never in ES), state-reset conformance (default-texture TexParameter/TexImage/TexBuffer no-ops, renderbuffer 0 unbind, vertex attrib 0 current value, ActiveTexture up to combined units, UBO binding count clamp), FramebufferTexture3D/TextureLayer slice attachments via glFramebufferTextureLayer, capability-driven FBO UNSUPPORTED for non-renderable colors, ReadPixels integer-ness mismatch error, single-value texture swizzle validation, and DirectGLES 1D/1D-array/2D-array texture emulation (2D/2D-array backend targets matching SPIRV-Cross ES 1D-as-2D shaders)
2026-07-16 22:41:54 -04:00
swung0x48
e2f873c95c
[Fix] (MG_Util/ShaderTranspiler): retry a legacy shader at 460 when it fails to parse as normalized 330 core, so sources using 420-era syntax without the matching #extension line keep compiling as they did on real drivers
2026-07-16 22:33:30 -04:00
swung0x48
efd7b47388
[Chore] (MG_Test): assert exact GL error counts - name-lifecycle regression tests per object family, plus fixtures that drain on setup and fail the test that leaks an unconsumed error
2026-07-16 22:12:12 -04:00
swung0x48
a08669df72
[Fix] (MG_Impl/GLImpl): stop recording GL errors on the delete/query paths of every object family - glDeleteBuffers/VertexArrays/Renderbuffers/Framebuffers must silently ignore unknown names and glIsTexture must never raise, while glBindSampler now reports INVALID_OPERATION like the other bind entry points
2026-07-16 22:11:43 -04:00
swung0x48
b8db509581
[Fix] (MG_Util/ShaderTranspiler): normalize legacy desktop shaders to GLSL 330
2026-07-16 21:39:39 -04:00
swung0x48
5d6b544021
[Fix] (MG_Impl/Texture): support anisotropic sampler parameters
2026-07-16 21:39:38 -04:00
swung0x48
346cd417ca
[Fix] (MG_Backend/DirectVulkan): fix ERROR-level vertex stream build
2026-07-16 21:36:22 -04:00
swung0x48
f61675e9ce
[Fix] (MG_Impl/Texture): validate the bound texture before dereferencing it in TexSubImage2D, and stop recording an error when glDeleteTextures is handed unknown names
2026-07-16 21:34:40 -04:00