Skip to content

BufferObject and UBO overhaul and partial update support for VertexBuffers#2868

Draft
riccardobl wants to merge 16 commits into
jMonkeyEngine:masterfrom
riccardobl:buffersov
Draft

BufferObject and UBO overhaul and partial update support for VertexBuffers#2868
riccardobl wants to merge 16 commits into
jMonkeyEngine:masterfrom
riccardobl:buffersov

Conversation

@riccardobl

@riccardobl riccardobl commented Jun 10, 2026

Copy link
Copy Markdown
Member

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:

  1. materials can seamlessly migrate to use UBOs instead of sparse uniforms

this is going to be useful if we get around implementing more complex rendering pipelines

  1. Only data that changes in VertexBuffers is uploaded to the gpu

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

  • make jme3-core/src/main/java/com/jme3/material/MatParamUniformBuffer.java smarter

zzuegg and others added 15 commits March 21, 2026 00:34
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

@gemini-code-assist gemini-code-assist Bot 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.

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.

Comment thread jme3-core/src/main/java/com/jme3/material/MatParamUniformBuffer.java Outdated
Comment thread jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java
Comment thread jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java Outdated
Comment thread jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java Outdated
@github-actions

Copy link
Copy Markdown

🖼️ 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 didn't expect to change anything visual:
Fix your changes so the screenshot tests pass.

If you did mean to change things:
Review the replacement images in jme3-screenshot-tests/build/changed-images to make sure they really are improvements and then replace and commit the replacement images at jme3-screenshot-tests/src/test/resources.

If you are creating entirely new tests:
Find the new images in jme3-screenshot-tests/build/changed-images and commit the new images at jme3-screenshot-tests/src/test/resources.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants