Skip to content

Commit 0b40bba

Browse files
authored
UBO/SSBO Improvements, Structs, BufferObject and sub data update (#1782)
reimplement UBOs and SSBOs in a more convenient and performant way.
1 parent 9a0ab09 commit 0b40bba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+4653
-1068
lines changed

jme-angle/src/native/angle

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 2319607679d7781ff9bab5e821a34574ecb0bcc3

jme3-core/src/main/java/com/jme3/material/Material.java

+82-66
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2024 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
4747
import com.jme3.renderer.queue.RenderQueue.Bucket;
4848
import com.jme3.scene.Geometry;
4949
import com.jme3.shader.*;
50+
import com.jme3.shader.bufferobject.BufferObject;
5051
import com.jme3.texture.Image;
5152
import com.jme3.texture.Texture;
5253
import com.jme3.texture.image.ColorSpace;
@@ -87,6 +88,16 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
8788
private boolean receivesShadows = false;
8889
private int sortingId = -1;
8990

91+
/**
92+
* Track bind ids for textures and buffers
93+
* Used internally
94+
*/
95+
public static class BindUnits {
96+
public int textureUnit = 0;
97+
public int bufferUnit = 0;
98+
}
99+
private BindUnits bindUnits = new BindUnits();
100+
90101
public Material(MaterialDef def) {
91102
if (def == null) {
92103
throw new IllegalArgumentException("Material definition cannot be null");
@@ -506,6 +517,18 @@ public void setParam(String name, VarType type, Object value) {
506517
}
507518
}
508519

520+
/**
521+
* Pass a parameter to the material shader.
522+
*
523+
* @param name the name of the parameter defined in the material definition (j3md)
524+
* @param value the value of the parameter
525+
*/
526+
public void setParam(String name, Object value) {
527+
MatParam p = getMaterialDef().getMaterialParam(name);
528+
setParam(name, p.getVarType(), value);
529+
}
530+
531+
509532
/**
510533
* Clear a parameter from this material. The parameter must exist
511534
* @param name the name of the parameter to clear
@@ -685,8 +708,7 @@ public void setColor(String name, ColorRGBA value) {
685708
* @param value the buffer object.
686709
*/
687710
public void setUniformBufferObject(final String name, final BufferObject value) {
688-
value.setBufferType(BufferObject.BufferType.UniformBufferObject);
689-
setParam(name, VarType.BufferObject, value);
711+
setParam(name, VarType.UniformBufferObject, value);
690712
}
691713

692714
/**
@@ -696,8 +718,7 @@ public void setUniformBufferObject(final String name, final BufferObject value)
696718
* @param value the buffer object.
697719
*/
698720
public void setShaderStorageBufferObject(final String name, final BufferObject value) {
699-
value.setBufferType(BufferObject.BufferType.ShaderStorageBufferObject);
700-
setParam(name, VarType.BufferObject, value);
721+
setParam(name, VarType.ShaderStorageBufferObject, value);
701722
}
702723

703724
/**
@@ -797,7 +818,7 @@ public void selectTechnique(String name, final RenderManager renderManager) {
797818
sortingId = -1;
798819
}
799820

800-
private int applyOverrides(Renderer renderer, Shader shader, SafeArrayList<MatParamOverride> overrides, int unit) {
821+
private void applyOverrides(Renderer renderer, Shader shader, SafeArrayList<MatParamOverride> overrides, BindUnits bindUnits) {
801822
for (MatParamOverride override : overrides.getArray()) {
802823
VarType type = override.getVarType();
803824

@@ -810,85 +831,80 @@ private int applyOverrides(Renderer renderer, Shader shader, SafeArrayList<MatPa
810831
Uniform uniform = shader.getUniform(override.getPrefixedName());
811832

812833
if (override.getValue() != null) {
813-
if (type.isTextureType()) {
814-
try {
815-
renderer.setTexture(unit, (Texture) override.getValue());
816-
} catch (TextureUnitException exception) {
817-
int numTexParams = unit + 1;
818-
String message = "Too many texture parameters ("
819-
+ numTexParams + ") assigned\n to " + toString();
820-
throw new IllegalStateException(message);
821-
}
822-
uniform.setValue(VarType.Int, unit);
823-
unit++;
824-
} else {
825-
uniform.setValue(type, override.getValue());
826-
}
834+
updateShaderMaterialParameter(renderer, type, shader, override, bindUnits, true);
827835
} else {
828836
uniform.clearValue();
829837
}
830838
}
831-
return unit;
832839
}
833840

834-
private int updateShaderMaterialParameters(Renderer renderer, Shader shader,
835-
SafeArrayList<MatParamOverride> worldOverrides, SafeArrayList<MatParamOverride> forcedOverrides) {
836841

837-
int unit = 0;
842+
private void updateShaderMaterialParameter(Renderer renderer, VarType type, Shader shader, MatParam param, BindUnits unit, boolean override) {
843+
if (type == VarType.UniformBufferObject || type == VarType.ShaderStorageBufferObject) {
844+
ShaderBufferBlock bufferBlock = shader.getBufferBlock(param.getPrefixedName());
845+
BufferObject bufferObject = (BufferObject) param.getValue();
846+
847+
ShaderBufferBlock.BufferType btype;
848+
if (type == VarType.ShaderStorageBufferObject) {
849+
btype = ShaderBufferBlock.BufferType.ShaderStorageBufferObject;
850+
bufferBlock.setBufferObject(btype, bufferObject);
851+
renderer.setShaderStorageBufferObject(unit.bufferUnit, bufferObject); // TODO: probably not needed
852+
} else {
853+
btype = ShaderBufferBlock.BufferType.UniformBufferObject;
854+
bufferBlock.setBufferObject(btype, bufferObject);
855+
renderer.setUniformBufferObject(unit.bufferUnit, bufferObject); // TODO: probably not needed
856+
}
857+
unit.bufferUnit++;
858+
} else {
859+
Uniform uniform = shader.getUniform(param.getPrefixedName());
860+
if (!override && uniform.isSetByCurrentMaterial()) return;
861+
862+
if (type.isTextureType()) {
863+
try {
864+
renderer.setTexture(unit.textureUnit, (Texture) param.getValue());
865+
} catch (TextureUnitException exception) {
866+
int numTexParams = unit.textureUnit + 1;
867+
String message = "Too many texture parameters (" + numTexParams + ") assigned\n to " + toString();
868+
throw new IllegalStateException(message);
869+
}
870+
uniform.setValue(VarType.Int, unit.textureUnit);
871+
unit.textureUnit++;
872+
} else {
873+
uniform.setValue(type, param.getValue());
874+
}
875+
}
876+
}
877+
878+
879+
880+
881+
private BindUnits updateShaderMaterialParameters(Renderer renderer, Shader shader, SafeArrayList<MatParamOverride> worldOverrides,
882+
SafeArrayList<MatParamOverride> forcedOverrides) {
883+
884+
bindUnits.textureUnit = 0;
885+
bindUnits.bufferUnit = 0;
886+
838887
if (worldOverrides != null) {
839-
unit = applyOverrides(renderer, shader, worldOverrides, unit);
888+
applyOverrides(renderer, shader, worldOverrides, bindUnits);
840889
}
841890
if (forcedOverrides != null) {
842-
unit = applyOverrides(renderer, shader, forcedOverrides, unit);
891+
applyOverrides(renderer, shader, forcedOverrides, bindUnits);
843892
}
844893

845894
for (int i = 0; i < paramValues.size(); i++) {
846895

847896
MatParam param = paramValues.getValue(i);
848897
VarType type = param.getVarType();
849898

850-
if (isBO(type)) {
851-
852-
final ShaderBufferBlock bufferBlock = shader.getBufferBlock(param.getPrefixedName());
853-
bufferBlock.setBufferObject((BufferObject) param.getValue());
854-
855-
} else {
856-
857-
Uniform uniform = shader.getUniform(param.getPrefixedName());
858-
if (uniform.isSetByCurrentMaterial()) {
859-
continue;
860-
}
861-
862-
if (type.isTextureType()) {
863-
try {
864-
renderer.setTexture(unit, (Texture) param.getValue());
865-
} catch (TextureUnitException exception) {
866-
int numTexParams = unit + 1;
867-
String message = "Too many texture parameters ("
868-
+ numTexParams + ") assigned\n to " + toString();
869-
throw new IllegalStateException(message);
870-
}
871-
uniform.setValue(VarType.Int, unit);
872-
unit++;
873-
} else {
874-
uniform.setValue(type, param.getValue());
875-
}
876-
}
899+
updateShaderMaterialParameter(renderer, type, shader, param, bindUnits, false);
877900
}
878901

879-
//TODO HACKY HACK remove this when texture unit is handled by the uniform.
880-
return unit;
902+
// TODO HACKY HACK remove this when texture unit is handled by the
903+
// uniform.
904+
return bindUnits;
881905
}
882906

883-
/**
884-
* Returns true if the type is Buffer Object's type.
885-
*
886-
* @param type the material parameter type.
887-
* @return true if the type is Buffer Object's type.
888-
*/
889-
private boolean isBO(final VarType type) {
890-
return type == VarType.BufferObject;
891-
}
907+
892908

893909
private void updateRenderState(Geometry geometry, RenderManager renderManager, Renderer renderer, TechniqueDef techniqueDef) {
894910
if (renderManager.getForcedRenderState() != null) {
@@ -1064,13 +1080,13 @@ public void render(Geometry geometry, LightList lights, RenderManager renderMana
10641080
renderManager.updateUniformBindings(shader);
10651081

10661082
// Set material parameters
1067-
int unit = updateShaderMaterialParameters(renderer, shader, overrides, renderManager.getForcedMatParams());
1083+
BindUnits units = updateShaderMaterialParameters(renderer, shader, overrides, renderManager.getForcedMatParams());
10681084

10691085
// Clear any uniforms not changed by material.
10701086
resetUniformsNotSetByCurrent(shader);
10711087

10721088
// Delegate rendering to the technique
1073-
technique.render(renderManager, shader, geometry, lights, unit);
1089+
technique.render(renderManager, shader, geometry, lights, units);
10741090
}
10751091

10761092
/**

jme3-core/src/main/java/com/jme3/material/Technique.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2024 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
3333

3434
import com.jme3.asset.AssetManager;
3535
import com.jme3.light.LightList;
36+
import com.jme3.material.Material.BindUnits;
3637
import com.jme3.material.TechniqueDef.LightMode;
3738
import com.jme3.material.logic.TechniqueDefLogic;
3839
import com.jme3.renderer.Caps;
@@ -162,9 +163,9 @@ Shader makeCurrent(RenderManager renderManager, SafeArrayList<MatParamOverride>
162163
* @param lights Lights which influence the geometry.
163164
* @param lastTexUnit the index of the most recently used texture unit
164165
*/
165-
void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
166+
void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) {
166167
TechniqueDefLogic logic = def.getLogic();
167-
logic.render(renderManager, shader, geometry, lights, lastTexUnit);
168+
logic.render(renderManager, shader, geometry, lights, lastBindUnits);
168169
}
169170

170171
/**

jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2024 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
3434
import com.jme3.asset.AssetManager;
3535
import com.jme3.light.*;
3636
import com.jme3.material.TechniqueDef;
37+
import com.jme3.material.Material.BindUnits;
3738
import com.jme3.math.ColorRGBA;
3839
import com.jme3.renderer.Caps;
3940
import com.jme3.renderer.RenderManager;
@@ -91,7 +92,7 @@ protected static ColorRGBA getAmbientColor(LightList lightList, boolean removeLi
9192

9293

9394
@Override
94-
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
95+
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) {
9596
Renderer renderer = renderManager.getRenderer();
9697
renderer.setShader(shader);
9798
renderMeshFromGeometry(renderer, geometry);

jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2024 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
3838
import com.jme3.light.SpotLight;
3939
import com.jme3.material.RenderState;
4040
import com.jme3.material.TechniqueDef;
41+
import com.jme3.material.Material.BindUnits;
4142
import com.jme3.math.ColorRGBA;
4243
import com.jme3.math.Quaternion;
4344
import com.jme3.math.Vector3f;
@@ -67,7 +68,7 @@ public MultiPassLightingLogic(TechniqueDef techniqueDef) {
6768
}
6869

6970
@Override
70-
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
71+
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) {
7172
Renderer r = renderManager.getRenderer();
7273
Uniform lightDir = shader.getUniform("g_LightDirection");
7374
Uniform lightColor = shader.getUniform("g_LightColor");

jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2024 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
3434
import com.jme3.asset.AssetManager;
3535
import com.jme3.light.*;
3636
import com.jme3.material.*;
37+
import com.jme3.material.Material.BindUnits;
3738
import com.jme3.material.RenderState.BlendMode;
3839
import com.jme3.math.*;
3940
import com.jme3.renderer.*;
@@ -262,17 +263,17 @@ private int setProbeData(RenderManager rm, int lastTexUnit, Uniform lightProbeDa
262263
}
263264

264265
@Override
265-
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
266+
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) {
266267
int nbRenderedLights = 0;
267268
Renderer renderer = renderManager.getRenderer();
268269
int batchSize = renderManager.getSinglePassLightBatchSize();
269270
if (lights.size() == 0) {
270-
updateLightListUniforms(shader, geometry, lights,batchSize, renderManager, 0, lastTexUnit);
271+
updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, 0, lastBindUnits.textureUnit);
271272
renderer.setShader(shader);
272273
renderMeshFromGeometry(renderer, geometry);
273274
} else {
274275
while (nbRenderedLights < lights.size()) {
275-
nbRenderedLights = updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, nbRenderedLights, lastTexUnit);
276+
nbRenderedLights = updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, nbRenderedLights, lastBindUnits.textureUnit);
276277
renderer.setShader(shader);
277278
renderMeshFromGeometry(renderer, geometry);
278279
}

jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2024 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
4040
import com.jme3.material.RenderState;
4141
import com.jme3.material.RenderState.BlendMode;
4242
import com.jme3.material.TechniqueDef;
43+
import com.jme3.material.Material.BindUnits;
4344
import com.jme3.math.ColorRGBA;
4445
import com.jme3.math.Vector3f;
4546
import com.jme3.math.Vector4f;
@@ -206,7 +207,7 @@ protected int updateLightListUniforms(Shader shader, Geometry g, LightList light
206207
}
207208

208209
@Override
209-
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
210+
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) {
210211
int nbRenderedLights = 0;
211212
Renderer renderer = renderManager.getRenderer();
212213
int batchSize = renderManager.getSinglePassLightBatchSize();

jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2024 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
3838
import com.jme3.light.PointLight;
3939
import com.jme3.light.SpotLight;
4040
import com.jme3.material.TechniqueDef;
41+
import com.jme3.material.Material.BindUnits;
4142
import com.jme3.math.ColorRGBA;
4243
import com.jme3.math.Matrix4f;
4344
import com.jme3.math.Vector3f;
@@ -171,7 +172,7 @@ private void updateLightListUniforms(Matrix4f viewMatrix, Shader shader, LightLi
171172
}
172173

173174
@Override
174-
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
175+
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) {
175176
Renderer renderer = renderManager.getRenderer();
176177
Matrix4f viewMatrix = renderManager.getCurrentCamera().getViewMatrix();
177178
updateLightListUniforms(viewMatrix, shader, lights);

0 commit comments

Comments
 (0)