Commit Graph
83 Commits
Author SHA1 Message Date
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 254cf1dc21 [Fix] (MG_Util/ShaderTranspiler, MG_State, MG_Impl/GLImpl, MG_Backend/DirectGLES): GL CTS uniform_block - coerce packed/shared block layouts to std140 at source preprocess (glslang rejects them when targeting SPIR-V; std140 is the only UBO layout the pipeline emits), GL-style block reflection (array "[0]" names, per-element struct-array expansion, unused members and declared-but-unread blocks stay active), vec4-padded GL_UNIFORM_BLOCK_DATA_SIZE, std140 array strides for struct-nested arrays (glslang reflects tight strides there), arrayed-block instances share the first instance member set, glDeleteShader-flagged names stay usable while attached, and backend ESSL emits against highp default precision so relaxed block members match across stages (KHR-GL33.shaders.uniform_block on llvmpipe: 659 Fail -> 828/828 Pass) 2026-07-16 12:09:11 -04:00
swung0x48 cf8f928db8 [Fix] (MG_Impl/GLImpl, MG_State): fallback UBO backing for optimizer-eliminated uniforms (null-MapUBO SIGSEGV in KHR-GL33 do_while loops) + per-element locations/offsets for array uniforms incl. nested struct arrays (size assert in KHR-GL33 struct.uniform); demote uniform write assert to log-and-clamp 2026-07-16 03:31:32 -04:00
swung0x48 22ac8a8c10 [Feat] (MG_Impl/GLImpl, MG_State): implement glBindFragDataLocationIndexed
Bind a fragment output to both a color number and a color index (0 or 1
for dual-source blending), and report the bound index back through
glGetFragDataIndex.

- ProgramObject now tracks a per-output color index alongside the
  location: SetExplicitFragmentOutIndex stores it, it is snapshotted into
  the linked map at link time (like the location map), and
  GetFragmentDataIndex returns it (0 by default) for an active output.
- glBindFragDataLocation becomes glBindFragDataLocationIndexed with index
  0, matching the GL definition, so it also resets a previously-bound
  index to 0.
- Validation: index must be 0 or 1 (GL_INVALID_VALUE); colorNumber is
  bounded by GL_MAX_DRAW_BUFFERS for index 0 and GL_MAX_DUAL_SOURCE_DRAW_BUFFERS
  (reported as 1) for index 1 (GL_INVALID_VALUE); a gl_ name is
  GL_INVALID_OPERATION.
- glGetFragDataIndex now returns the real bound index instead of a
  hardcoded 0.

The index is tracked for reflection but is not yet plumbed into dual-source
blend rendering, and shader-side layout(index=) qualifiers are not
reflected -- both documented at the call sites.

Tests: index round-trip through a re-link (bind 1 -> GetFragDataIndex == 1;
glBindFragDataLocation resets to 0), plus the validation error table;
mutation-verified end to end. ProgramTest 24/24.
2026-07-11 00:39:23 -04:00
swung0x48 bebe534bad [Fix] (MG_Impl/GLImpl): stop double-recording GL errors for a bad program handle
glBindFragDataLocation, glGetFragDataLocation and glGetFragDataIndex each
recorded a redundant GL_INVALID_OPERATION on top of the error that
TryToGetProgramObject already recorded (GL_INVALID_VALUE for an unknown
name, GL_INVALID_OPERATION for a non-program object). One bad call thus
queued two errors, so an app calling glGetError twice saw a spurious
second error, and any following code that expects a clean error queue
(e.g. a later test) picked up the stale one.

Drop the second RecordError from all three call sites and rely on the
single error TryToGetProgramObject already reports -- matching the clean
`if (!programObject) return;` pattern the rest of GL_Program.cpp uses. The
first, app-visible error is unchanged; only the redundant second is gone.

ProgramTest's invalid-handle case now asserts exactly one error (mutation-
verified: reintroducing the second record fails it) and keeps a defensive
error-queue drain. ProgramTest 24/24.
2026-07-11 00:19:33 -04:00
swung0x48 9ffcb23877 [Feat] (MG_Impl/GLImpl): implement glGetFragDataIndex
Fill the stubbed GL 3.3 Core glGetFragDataIndex, mirroring its already-
implemented sibling glGetFragDataLocation: validate the program object and
link status, then return the fragment color index the name binds to.

Every active user-defined output uses color index 0. MobileGL does not yet
track dual-source (index 1) bindings -- glBindFragDataLocationIndexed and
the layout(index = 1) qualifier are unsupported -- so the result is exact
for any program that does not use dual-source blending; a name that is not
an active output (including gl_ built-ins) returns -1.

Tests: assertions on the existing linked-program test (valid output -> 0,
unknown name -> -1) plus a standalone invalid-handle case. The invalid-
handle test drains the error queue it produces so no stale error leaks
into a later test (the ProgramTest fixture does not reset it). ProgramTest
24/24.
2026-07-11 00:03:08 -04:00
swung0x48 561d8992bc [Feat] (MG_Impl/GLImpl, MG_State): implement glGetActiveUniformsiv (UBO reflection query)
Completes the uniform-block reflection chain: glGetUniformIndices, glGetActiveUniformName
and glGetActiveUniformBlockiv were already implemented; glGetActiveUniformsiv was the last
stub. Supports all 8 GL 3.3 Core pnames:

* GL_UNIFORM_TYPE / SIZE / NAME_LENGTH / BLOCK_INDEX / OFFSET / ARRAY_STRIDE come straight from
  glslang's TObjectReflection (the same reflection the existing uniform queries use).
* GL_UNIFORM_IS_ROW_MAJOR from the member's TType layout qualifier, guarded by isMatrix() so a
  scalar in a layout(row_major) block does not wrongly report 1.
* GL_UNIFORM_MATRIX_STRIDE is derived: glslang exposes no matrix stride, so it is computed from the
  std140 rule (each column/row vector rounded up to a vec4), which matches the std140 layout
  MobileGL's SPIR-V path emits. Evaluates to 16 for every GL 3.3 float matrix.

The -1-vs-0 distinction is handled explicitly: OFFSET / ARRAY_STRIDE / MATRIX_STRIDE / BLOCK_INDEX
return -1 for a default-block uniform (glslang gives arrayStride 0 there, so it is gated on block
membership), while ARRAY_STRIDE / MATRIX_STRIDE return 0 for a non-array / non-matrix member that IS
in a block. Errors: GL_INVALID_VALUE for uniformCount<0, any index >= active uniform count, or a
never-generated program name; GL_INVALID_OPERATION for a live shader name; GL_INVALID_ENUM for an
unaccepted pname (e.g. the GL 4.2 GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX). All validation runs before
any write, so params is untouched on error. There is no "not linked" error -- an unlinked program has
zero active uniforms, so any index raises GL_INVALID_VALUE.

Also fix GetActiveUniformArraySize, which returned glslang's TObjectReflection.size verbatim: that
field only carries the element count for a non-block array and reports 1 for a block array member,
so GL_UNIFORM_SIZE (and glGetActiveUniform's size out-param, and glGetProgramResourceiv's
GL_ARRAY_SIZE) wrongly reported 1 for an array inside a UBO. Take the count from the TType instead,
which is authoritative for both cases.

Covered by 3 ProgramTest cases (std140 block with scalar/array/mat4 + a default-block sampler, a
row_major variant, and the six error cases) that link real shaders and assert every pname value.
2026-07-10 19:54:33 -04:00
swung0x48 d40f753983 [Fix] (MG_State, MG_Impl, MG_Backend): conformant current generic vertex attribute values
GL 3.3 Core: a shader input whose generic attribute array is disabled reads that
attribute's current value (per-context state, default (0,0,0,1)). Four defects made
that path non-conformant, three of them silently.

* Out-of-bounds current-value reads. m_currentVertexAttributes held 16 entries while
  the DirectVulkan draw path walked shader input locations 0..31 and GL_MAX_VERTEX_ATTRIBS
  was advertised straight from the device (commonly 32). The only guard was MOBILEGL_ASSERT,
  which expands to nothing outside debug builds. Grow the storage capacity to 32, advertise
  min(device limit, capacity), validate against that dynamic limit, and give the accessors
  real runtime bounds checks. Replace the literal 32 loops with the constant, and pin
  MAX_VERTEX_ATTRIBS to the Uint32 mask width and to vertexInputTypes' bound with
  static_asserts so the two can no longer drift apart -- that drift was the bug.

* DirectGLES never fed current values to the driver. Values were stored in MG_State only,
  so a disabled attribute always rendered as the ES driver's own untouched (0,0,0,1) while
  DirectVulkan rendered it correctly: identical GL code, different pixels per backend.
  Add SyncCurrentVertexAttributeValues() to the draw prologue, and hoist the
  glType -> (base type, component count) dispatch into MG_State::GLState so both backends
  resolve the semantics from one place instead of it living inside VulkanRenderer.

* Enabled arrays the backend could not map were silently demoted to the current value.
  ToVkVertexFormat had no DataType::Float16 case, so a GL_HALF_FLOAT array fell to
  VK_FORMAT_UNDEFINED, dropped out of the vertex input state, and became indistinguishable
  from a disabled array: the geometry rendered a constant colour with GL_NO_ERROR. Add the
  Float16 mapping, track an unsupportedAttribMask, and hard-fail the draw before pipeline
  creation so no synthetic attribute is baked into a cached VkPipeline.

* glGetVertexAttrib{fv,iv,Iiv,Iuiv}(GL_CURRENT_VERTEX_ATTRIB) returned before any index
  validation, reading past the array instead of raising GL_INVALID_VALUE.

Also resolve ProgramObject::DoReflection's "TODO: get from backend" 16-location clamp,
which capped the new DirectGLES sync at locations 0..15; report GL_MAX_VERTEX_ATTRIBS
through the same helper the validators use, so the clamp cannot be bypassed; and bound
vertex binding indices by the same dynamic limit, since the default attribute -> binding
mapping is the identity.

Add a "Vertex attributes" driver POST row to both backends: FAIL below the GL 3.3 Core
minimum of 16, WARN above MobileGL's storage capacity (clamped, extra attributes unusable),
PASS in between -- making the driver/host mismatch that caused the out-of-bounds read
visible instead of silently swallowed.

Covered by 7 new regression tests (each verified to fail against the previous behaviour).
2026-07-10 11:23:16 -04:00
swung0x48andClaude Fable 5 a6a5edf573 [Perf] (MG_Backend/DirectGLES, MG_Impl): cache link-time lookups, bound unit scans, honor eglSwapInterval
- BackendProgramObjectImpl::CacheResourceLocations resolves every
  glGetUniformBlockIndex / glGetUniformLocation string query once per
  link and establishes the block binding points there. Per draw,
  BindCurrentProgramWithResources now uses the cached indices, re-issues
  glUniform1i only when a sampler's unit actually changed (program state
  persists), uploads the global UBO only when its content version moved,
  and skips redundant glUseProgram binds (guard reset on program-name
  reuse, MakeCurrent, and every explicit glUseProgram(0)). The caches are
  invalidated through ProgramObject's link version, which also makes a
  relinked program finally re-sync its backend program.
- Track a texture-unit high-water mark (fed by glBindTexture /
  glBindTextureUnit / glBindSampler / glBindImageTexture) so the two
  per-draw unit scans (MAX_TEXTURE_IMAGE_UNITS is 192) and the
  texture-deletion unbind loop only walk units that were ever touched.
- Forward the app's eglSwapInterval to the native EGL surface through a
  new BackendObject::SetEGLSwapInterval hook (applied immediately when
  the surface exists, otherwise deferred to surface creation /
  MakeCurrent). "VSync off" finally reaches the hardware - DirectGLES
  was hard-locked to the display refresh before.

The driver-side cost of the per-draw string lookups was about half of a
30% Adreno driver hotspot; libMobileGL's share of the vanilla render
thread fell from 22% to 9% (simpleperf, Adreno 830).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 12:12:51 +00:00
swung0x48 51d9fa91ed [Fix] (MG_Impl/GLImpl, MG_Backend): fix piglit texture and buffer cases 2026-07-03 08:51:22 +08:00
swung0x48 03696f8a1a [Fix] (MG_Impl/GLImpl, MG_State, MG_Backend): validate image uniform state 2026-07-03 02:03:23 +08:00
swung0x48 71f5ba9601 [Fix] (MG_Impl/GLImpl): handle program resource names [skip ci] 2026-07-02 19:10:50 +08:00
swung0x48 2e14b44349 [Fix] (MG_Impl/GLImpl): validate compute program queries [skip ci] 2026-07-02 19:04:23 +08:00
swung0x48 ac66ea7790 [Fix] (MG_Impl/GLImpl): validate program interface queries [skip ci] 2026-07-02 18:56:30 +08:00
swung0x48 633a25b456 [Fix] (MG_Impl/GLImpl, MG_State/GLState): validate frag data link locations [skip ci] 2026-07-02 16:47:13 +08:00
swung0x48 b9de562491 [Fix] (MG_Impl/GLImpl, MG_State/GLState): fix frag data location queries [skip ci] 2026-07-02 16:20:43 +08:00
swung0x48 ced7f28898 [Fix] (MG_Impl/GLImpl, MG_State/GLState): reject unlinked empty programs [skip ci] 2026-07-02 14:37:29 +08:00
swung0x48 3c643d943a [Fix] (MG_Impl/GLImpl): fix more OpenGL 3.x piglit cases 2026-07-02 12:36:58 +08:00
BZLZHH 83a6f24f93 Merge remote-tracking branch 'origin/Feat/Backend-Direct-Vulkan' into Agent/CodexAudit
# Conflicts:
#	MobileGL/MG_Backend/BackendObject.h
#	MobileGL/MG_Backend/DirectGLES/Managers.cpp
#	MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp
#	MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp
#	MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp
#	MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp
#	MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp
#	MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp
#	MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp
#	MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp
#	MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.h
#	MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp
#	MobileGL/MG_Impl/GLImpl/Program/GL_Program.h
#	MobileGL/MG_Impl/GLImpl/Sync/GL_Sync.cpp
#	MobileGL/MG_Impl/GLImpl/Sync/GL_Sync.h
#	MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp
#	MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp
#	MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h
#	MobileGL/MG_State/GLState/BufferState/BufferObject.cpp
#	MobileGL/MG_State/GLState/BufferState/BufferObject.h
#	MobileGL/MG_Util/BackendLoaders/Vulkan/Loader.cpp
#	MobileGL/MG_Util/BackendLoaders/Vulkan/Loader.h
2026-06-09 21:18:12 +08:00
BZLZHH 727939af5b [Fix] (MG_Impl, MG_State, MG_Backend, MG_Util): Do source audit by Codex. 2026-06-09 15:34:19 +08:00
swung0x48 cf165c0db5 [Fix] (MG_Backend/DirectVulkan): support Voxy rendering
Implemented:

- Advertise Voxy-required DirectVulkan extensions without raising the reported OpenGL version.

- Add DirectVulkan compute, indirect draw count, DSA, readback, and buffer state paths needed by Voxy.

Fixed:

- Enable Vulkan shaderInt64 and drawIndirectFirstInstance so Voxy baseInstance-driven LOD draws address the correct section data.

- Fix DirectVulkan synchronization, framebuffer, texture readback, and shader interface handling used by Voxy and Minecraft screenshots.

Tests:

- Add MG_Test coverage for DirectVulkan extension advertising, DSA buffer/texture/framebuffer/vertex-array behavior, persistent mapped readback, and shader/program paths.
2026-06-09 00:37:37 +08:00
swung0x48 19ada4b8f9 [Fix]: fix glmark2 crash
- deal with legacy GLSL syntax (attribute/varying/gl_FragColor/texture2D/etc.)
- implement glGet GL_SHADER_SOURCE_LENGTH, and make sure returns
  original shader source
- expose proper extensions (GL_ARB_depth_texture)
- support env var MOBILEGL_LOG_FILE_PATH
- unit tests to test against those changes
2026-06-07 11:08:38 +08:00
swung0x48 24efb0bb17 [Fix] (MG_Impl/Program): implement direct state uniform updates 2026-06-06 17:27:09 +08:00
swung0x48 5cfe9c8998 [Feat] (MG_Backend/DirectVulkan): support compute shaders 2026-06-05 11:52:10 +08:00
swung0x48 3bd8a62aa8 [Feat] (MG_Backend/DirectGLES): support compute shaders 2026-06-05 10:41:23 +08:00
swung0x48 633b3d3b0a [Feat] (MG_State/RenderState, MG_Backend/DirectVulkan): make Distant
Horizon work
- Implement BlendEquation/CullFaceMode/PointSize/PolygonMode
- Implement GetFramebufferAttachmentParameter*
- Downgrade some color attachment resolve failure
- Downgrade some overly-strict shader stage linkage check (don't check
  on unused input var)
2026-05-12 12:38:19 +08:00
swung0x48 8e4a4359b4 [Chore] (MG_Backend/DirectVulkan): eliminate vague texture binding fallbacks 2026-05-05 18:34:44 +08:00
BZLZHH 15e24cda78 [Perf|Improvement] (All): Improve performance & optimize code. 2026-02-23 16:00:38 +08:00
BZLZHH 8413874e82 [Feat|Refactor] (MG_Backend|MG_Impl): Implement BackendObject, replacing previous methods. 2026-02-18 10:36:56 +08:00
BZLZHH 0cf9d9223d [Feat|Perf] (*/BufferState): Improve dirty mark for Buffer. 2026-02-02 02:25:41 +08:00
swung0x48 31b3053c56 [Chore] (MG_Util/ShaderTranspiler): rename function, more log 2026-01-30 16:44:33 +08:00
BZLZHH 20fbfc2956 [Chore] (LICENSE): Switch project license to LGPLv3. 2026-01-18 09:33:33 +08:00
BZLZHH 3714e275ab [Chore] (All): Update copyright year in source code files. 2026-01-01 00:42:06 +08:00
BZLZHH e7d9da42dc [Chore] (All): Adjust copyright declaration. 2025-12-31 21:49:54 +08:00
BZLZHH 58b620dee3 [Feat] (MG_Backend|MG_State/ProgramState): Add default fragment shader if missing for backends requiring FS. 2025-12-31 21:09:19 +08:00
BZLZHH 8ed8efe347 [Chore] (All): Add standardized source file header and update script. 2025-12-31 15:45:34 +08:00
BZLZHH 9cd749b707 [Improvement] (All): Better assertion. 2025-11-23 10:27:01 +08:00
swung0x48 e3f73291e9 [Fix] (MG_Impl/GL_Program): fix GetUniform_State for mat3 alignment issues 2025-11-21 22:24:47 +08:00
swung0x48 2709b9754f [Fix] (MG_Impl/Program): fixing UniformMatrix3fv improper alignment 2025-11-18 11:16:29 +08:00
BZLZHH e85b067314 [Fix] (MG_Backend/DirectGLES|MG_Impl/Program): Correct UBO binding. 2025-11-15 21:37:08 +08:00
swung0x48 0d26f49d0b [Fix] (GLImpl/Program): fix log name error 2025-11-13 14:47:05 +08:00
swung0x48 b3b304e9e6 [Feat]: Implement glBindFragDataLocation and glGetFragDataLocation 2025-11-13 13:23:37 +08:00
swung0x48 cf87891b35 [Fix] (MG_Impl/GL_Program): emit missing gl error 2025-11-13 10:51:38 +08:00
swung0x48 b04481e6da [Chore] (MG_State/ProgramObject): rename attrib to vertex in for clarity 2025-11-13 10:50:37 +08:00
swung0x48 7228b01c2d [Fix] (GLImpl/Program, MG_Backend/DirectGLES): guard against not linked program object 2025-11-06 23:21:23 +08:00
swung0x48 a6ffb24f30 [Fix] (MG_State/Program): fix ubo name mistaken for uniform name 2025-11-05 16:18:35 +08:00
swung0x48 ef1924d7f9 [Feat] (MG_State/Program, DirectGLES): plumb ubo to backend 2025-11-05 15:37:10 +08:00
swung0x48 c39c03d866 [Fix] (MG_Impl/Program): DeleteShader name check bug 2025-11-05 15:12:37 +08:00
swung0x48 1ea32e8538 [Fix] (GL_Impl/Program): fix logging 2025-11-02 11:22:52 +08:00
swung0x48 c69e83735c [Chore] (GL_Impl/Program): add more logging 2025-11-02 11:15:42 +08:00