BufferObject and UBO overhaul and partial update support for VertexBuffers#2868
BufferObject and UBO overhaul and partial update support for VertexBuffers#2868riccardobl wants to merge 16 commits into
Conversation
The material system was using wrong binding points for shader storage and uniform buffer objects, causing data to be bound to incorrect slots. - GLRenderer.updateShaderBufferBlock() now queries the actual binding from the compiled shader (glGetActiveUniformBlocki for UBOs, glGetProgramResourceiv for SSBOs) and respects layout(binding=N). Falls back to blockIndex when no explicit binding is declared. - Remove premature renderer.setShaderStorageBufferObject/ setUniformBufferObject calls from Material.updateShaderMaterialParameter that used a sequential counter as binding point. - Cache binding on ShaderBufferBlock (per-shader) instead of BufferObject (per-buffer), since the same buffer can be bound at different points in different shaders. - Add glGetActiveUniformBlocki to GL3 and glGetProgramResourceiv + GL_BUFFER_BINDING to GL4 with implementations in both LWJGL backends. - BufferObject.initializeEmpty() now calls setUpdateNeeded() so the GPU buffer gets allocated on first use. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds 5 parameterized screenshot tests that verify SSBO binding point resolution through the material system. Each test creates 3 SSBOs (red, green, blue) and checks that the shader output is white. - NoBindings: no explicit layout(binding=N) on any block - ExplicitBindings: all blocks have explicit non-zero bindings - Binding0OnSecond: second block has layout(binding=0) - MixedBindings: mix of explicit non-zero and implicit bindings - Collision (KNOWN_TO_FAIL): unbound block at blockIndex=1 collides with another block's explicit layout(binding=1), producing magenta instead of white — demonstrates the binding point ambiguity bug Also fixes BufferObject.setData() which was destroying the input parameter instead of this.data and was not calling setUpdateNeeded(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion Replaces the per-block binding resolution with a two-pass approach in resolveBufferBlockBindings() that runs once per shader program: Pass 1: query all block bindings from the compiled shader. Pass 2: detect duplicate binding points and reassign colliding blocks to unique free binding points. This fixes the case where an unbound block's default binding (0) collides with another block's explicit layout(binding=N). The collision test now passes as MUST_PASS instead of KNOWN_TO_FAIL. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UBOs and SSBOs use separate GL binding namespaces (GL_UNIFORM_BUFFER vs GL_SHADER_STORAGE_BUFFER), so a UBO at binding 0 does not collide with an SSBO at binding 0. Track them independently in the collision detection pass to avoid unnecessary reassignments. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds compile-time validation that rejects shaders using layout(binding=0) on a buffer block that is not the first declared block. The GL query cannot distinguish explicit binding=0 from the default, so this case would silently produce incorrect bindings. The error message tells the user to use a non-zero binding or declare the block first in the shader. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rageBlockBinding Use the renderer's intBuf1 and intBuf16 instance fields instead of allocating new IntBuffers on each call. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java # jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOBinding.vert # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOBinding0OnSecond.frag # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOBinding0OnSecond.j3md # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOCollision.frag # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOCollision.j3md # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOExplicitBindings.frag # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOExplicitBindings.j3md # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOMixedBindings.frag # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBOMixedBindings.j3md # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBONoBindings.frag # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/TestSSBOBinding/SSBONoBindings.j3md # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/org.jmonkeyengine.screenshottests.ssbo.TestSSBOBinding.testSSBOBinding_Binding0OnSecond_f1.png # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/org.jmonkeyengine.screenshottests.ssbo.TestSSBOBinding.testSSBOBinding_Collision_f1.png # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/org.jmonkeyengine.screenshottests.ssbo.TestSSBOBinding.testSSBOBinding_ExplicitBindings_f1.png # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/org.jmonkeyengine.screenshottests.ssbo.TestSSBOBinding.testSSBOBinding_MixedBindings_f1.png # jme3-screenshot-tests/jme3-screenshot-tests-desktop/src/main/resources/org.jmonkeyengine.screenshottests.ssbo.TestSSBOBinding.testSSBOBinding_NoBindings_f1.png
…ffer update and support custom named VertexBuffers
There was a problem hiding this comment.
Code Review
This pull request introduces automatic material-parameter Uniform Buffer Object (UBO) packing and custom vertex attributes in jMonkeyEngine. Key additions include the MatParamUniformBuffer class for packing material parameters, updates to Mesh and VertexBuffer to support custom attributes and partial GPU uploads, and enhanced buffer binding resolution and collision detection in GLRenderer. The review feedback focuses on critical performance optimizations and bug prevention, recommending that MatParamUniformBuffer cache and reuse its direct ByteBuffer to avoid per-frame allocations, use bulk put operations and ByteBuffer.equals for faster buffer operations, strip comments from shader sources to prevent false-positive validation crashes, and add a null check on vertex buffer data to avoid a potential NullPointerException.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
🖼️ Screenshot tests have failed. The purpose of these tests is to ensure that changes introduced in this PR don't break visual features. They are visual unit tests. 📄 Where to find the report:
✅ If you did mean to change things: ✨ If you are creating entirely new tests: Note; it is very important that the committed reference images are created on the build pipeline, locally created images are not reliable. Similarly tests will fail locally but you can look at the report to check they are "visually similar". See https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-screenshot-tests/README.md for more information Contact %40richardTingle (aka richtea) for guidance if required |
This builds on top and supersedes #2647 and it includes all its fixes and some more, plus layout std430, refactor of ssdm shadows to use buffer objects, reservation of UBOs id for engine specific data (for future extension), support of UBO based material params, refactoring of VertexBuffers on top of BufferObject to support partial buffer updates.
The two main features the engine will have after this pr is merged, are:
this is going to be useful if we get around implementing more complex rendering pipelines
This means that if you have a very large buffer where only some elements are updated per frame, only the elements that change are uploaded to the gpu. This minimizes the bandwidth usage for things like instancing and particles, making them much more performant.
(wip, targeting 3.11 release)
TODO
jme3-core/src/main/java/com/jme3/material/MatParamUniformBuffer.javasmarter