Three pieces of queryable buffer state were missing, all of them read by the
KHR-GL40.draw_indirect basic-binding-* and basic-buffer-* cases:
- GL_DRAW_INDIRECT_BUFFER_BINDING had no case in glGetIntegerv, so it raised
GL_INVALID_ENUM and left the caller's variable untouched (the test read back its own
-9999 sentinel). GL_DISPATCH_INDIRECT_BUFFER_BINDING right next to it was already
handled; this is the same two lines against BufferTarget::DrawIndirect. Because
glGetBooleanv/glGetFloatv/glGetDoublev all widen from the integer path, one case
fixes all four getters.
- GL_BUFFER_ACCESS answered 0 for an unmapped buffer. Its initial value is
GL_READ_WRITE and glUnmapBuffer restores it (GL 4.6 core table 6.2); 0 is not a legal
value of that state at all, and the test threw on the unrecognised enum.
- GL_BUFFER_ACCESS_FLAGS was not implemented, so it fell through to the invalid-pname
arm. It is the MapBufferRange bitfield verbatim, which the mapping access flags
already hold in normalised form - glMapBuffer's access enum is converted on the way
in - so it converts straight back out, and reads zero while unmapped.
Buffer contents live in a CPU shadow that every read - MapBuffer, MapBufferRange,
GetBufferSubData, CopyBufferSubData - resolves against, and backend transfer ops only
ever push the shadow outwards. Two paths already knew the GPU can write a buffer on
its own and mirrored the result back by hand (ReadPixels into a pixel-pack buffer,
the transform feedback capture at EndTransformFeedback); a shader storage buffer
written by a draw or a dispatch had no such path at all, so the map handed the
application the bytes from before the dispatch.
Nothing exercised it until now because GL 3.3 has no compute stage. Every
KHR-GL40.texture_gather case ends by dispatching a compute shader that writes its
sampled texel into an SSBO and comparing the mapped result, and all 71 read back the
zero-filled shadow.
Adds the missing direction as a backend op: BufferObject::MarkGpuWritten flags a
buffer the GPU may have moved ahead of the shadow, SyncGpuWrites pulls it back at
every read point, and DirectGLES implements the readback with a plain read map of the
ES buffer. The flag is raised where the storage-buffer points are bound for the
upcoming draw or dispatch, which is the last moment the set of exposed buffers is
known, and cleared by the readback - so a buffer nothing writes costs one bool test
per map. Backends that cannot read their storage back leave the op null and keep
today's behaviour; a GPU-resident (coherent persistent) buffer needs nothing, since
its reads already resolve against the memory the shader wrote.
Drops the texture_gather failures from 71/75 to 25/75 with no crashes left.
BindBufferBase and BindBufferRange bind the buffer to the indexed point AND to the
generic binding point of the same target (GL 4.6 core 6.1.1); only the indexed half
was implemented. Applications lean on the second half constantly, because it is what
makes the set-up idiom work:
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, size, nullptr, GL_DYNAMIC_DRAW);
With the generic point left at 0 the glBufferData raised GL_INVALID_OPERATION and
the buffer kept its zero size, so the later glMapBufferRange over it failed the
offset+length bound and returned nullptr. The whole KHR-GL40.texture_gather group
verifies its result through exactly that sequence and dereferences the map's return
value without checking it, so 51 of its 75 cases took the process down with a
SIGSEGV inside the test.
Unbinding propagates the same way: buffer 0 clears both points.
First stage of GL 3.0 transform feedback: glTransformFeedbackVaryings /
glGetTransformFeedbackVarying / glBeginTransformFeedback /
glEndTransformFeedback were unimplemented stubs. This adds
- per-program capture state: requested varyings apply on the next link and
resolve against the last vertex-processing stage's linker objects (with
gl_Position/gl_PointSize handled as builtins), failing the link on
unknown or duplicate names or exceeded interleaved/separate limits, with
offsets and strides computed per GL rules;
- context Begin/End state with the GL 3.3 error semantics: invalid
primitive modes, redundant Begin/End, missing program or capture-buffer
bindings, primitive-mode compatibility at draw time, and the
while-active prohibitions on rebinding capture buffers, switching
programs, and relinking the captured program;
- GetProgramiv TRANSFORM_FEEDBACK_* queries and a 4-slot bound on indexed
GL_TRANSFORM_FEEDBACK_BUFFER binding points.
KHR-GL33.transform_feedback api_errors/linking_errors/get_xfb_varying now
pass; GPU-side capture is the remaining stage.
Two previously-stubbed GL 3.3 Core entry points.
glMultiDrawArrays: mirrors the existing glMultiDrawElements(BaseVertex)
architecture end to end -- a new MultiDrawArrays backend function-table
slot dispatched from the frontend after program/primitive-mode validation
(plus a drawcount < 0 -> GL_INVALID_VALUE guard).
- DirectGLES: PrepareForDraw once, then loop native glDrawArrays with the
same per-range client-side array upload the single DrawArrays does.
- DirectVulkan: build a MultiDrawCmd payload and hand it to a new
VulkanRenderer::MultiDrawArrays, which does one SetupDraw over the union
of the sub-draw vertex ranges and then a vkCmdDraw per range (mirrors
VulkanRenderer::MultiDrawElements).
glGetBufferSubData: reads a range of the bound buffer's CPU shadow into
client memory via a new BufferObject::DownloadSubData, with the same
validation shape as BufferSubData (INVALID_VALUE for negative/overflowing
range, INVALID_OPERATION for no bound buffer or a non-persistent mapped
buffer). The shadow reflects CPU writes and backend write-backs but not
arbitrary GPU-side writes, which is documented on the method.
Tests: 2 BufferTest cases for glGetBufferSubData (round-trip read of a
middle range and the whole buffer, plus out-of-range/negative/no-buffer
errors). BufferTest 32/32, SanityTest 30/30, VertexArrayTest 42/42;
library builds clean. (The glMultiDrawArrays draw paths are not
runtime-testable on this host and are compile-verified against the tested
MultiDrawElements pattern.)
Add a separate binding-point model to VertexArrayObject with eager
resolution into the flat per-attribute view backends already consume.
Implements glBindVertexBuffer(s), glVertexAttrib(I)Format,
glVertexAttribBinding, glVertexBindingDivisor and the DSA variants
(glVertexArrayAttribBinding, glVertexArrayBindingDivisor,
glVertexArrayVertexBuffers), fixing glVertexArrayVertexBuffer which
previously conflated binding index with attribute index. Multi-bind
(glBindBuffersBase/Range) loops over the single-bind entry points.
Needed by Flywheel's indirect backend (GlVertexArrayDSA setup path).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 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
Feat: implement MG_Impl/Buffer
Feat: implement MG_State/ErrorState and integrate it into MG_State/GLContext
Feat: add buffer deletion management
Feat: introduce `INSERTION_POINT` (https://github.com/MobileGL-Dev/MobileGLCodeManager)
Feat: add tests about MG_Impl/Buffer and buffer deletion feature
Feat: add several converters
Fix: fix some compiling errors
Fix: fix some incorrect behaviors in MG_State/Buffer
Improvement: remove some current statements at the beginning of the source file, which will be added uniformly soon
Improvement: optimize some naming