Skip to content

Commit 7e9351f

Browse files
Copilotriccardobl
andcommitted
Clamp maxSinglePassLightBatchSize by FragmentUniformVectors; init via constructor
Co-authored-by: riccardobl <4943530+riccardobl@users.noreply.github.com> Agent-Logs-Url: https://github.com/jMonkeyEngine/jmonkeyengine/sessions/7f45fdc6-5fdc-4d0d-8618-5874f95dbf29
1 parent b8a6d82 commit 7e9351f

1 file changed

Lines changed: 35 additions & 2 deletions

File tree

jme3-core/src/main/java/com/jme3/renderer/RenderManager.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ public class RenderManager {
8787

8888
private static final Logger logger = Logger.getLogger(RenderManager.class.getName());
8989

90+
/**
91+
* Number of vec4 fragment uniform vectors consumed per light in g_LightData
92+
* (lightColor, lightData1, lightData2/spotDir).
93+
*/
94+
private static final int VEC4_UNIFORMS_PER_LIGHT = 3;
95+
/**
96+
* Fraction of the total fragment uniform budget reserved for shader
97+
* parameters other than g_LightData (material params, transforms, etc.).
98+
* A value of 4 means one quarter is reserved.
99+
*/
100+
private static final int RESERVED_UNIFORM_FRACTION = 4;
101+
90102
private final Renderer renderer;
91103
private final UniformBindingManager uniformBindingManager = new UniformBindingManager();
92104
private final ArrayList<ViewPort> preViewPorts = new ArrayList<>();
@@ -109,7 +121,7 @@ public class RenderManager {
109121
private LightFilter lightFilter = new DefaultLightFilter();
110122
private TechniqueDef.LightMode preferredLightMode = TechniqueDef.LightMode.MultiPass;
111123
private int singlePassLightBatchSize = 1;
112-
private int maxSinglePassLightBatchSize = 32;
124+
private int maxSinglePassLightBatchSize;
113125
private final MatParamOverride boundDrawBufferId = new MatParamOverride(VarType.Int, "BoundDrawBuffer", 0);
114126
private Predicate<Geometry> renderFilter;
115127

@@ -125,6 +137,7 @@ public RenderManager(Renderer renderer) {
125137
this.forcedOverrides.add(boundDrawBufferId);
126138
// register default pipeline context
127139
contexts.put(PipelineContext.class, new DefaultPipelineContext());
140+
setMaxSinglePassLightBatchSize(16);
128141
}
129142

130143
/**
@@ -1098,7 +1111,10 @@ public void setSinglePassLightBatchSize(int singlePassLightBatchSize) {
10981111
* Returns the maximum number of lights allowed in a single pass batch.
10991112
*
11001113
* <p>The batch size will never be auto-scaled beyond this value.
1101-
* The default is 16.
1114+
* The default is 16, further clamped at construction time by the hardware's
1115+
* {@link Limits#FragmentUniformVectors} capacity (each light consumes 3 vec4
1116+
* uniforms; a quarter of the available budget is reserved for other shader
1117+
* parameters).
11021118
*
11031119
* @return the maximum single pass light batch size.
11041120
*/
@@ -1109,6 +1125,13 @@ public int getMaxSinglePassLightBatchSize() {
11091125
/**
11101126
* Sets the maximum number of lights allowed in a single pass batch.
11111127
*
1128+
* <p>The requested value is clamped to a hardware-safe upper bound derived
1129+
* from the renderer's {@link Limits#FragmentUniformVectors} capacity.
1130+
* Each light consumes 3 vec4 uniforms in {@code g_LightData}; one quarter
1131+
* of the available uniform budget is reserved for other shader parameters.
1132+
* If the hardware limit cannot be queried (e.g., renderer not yet
1133+
* initialised), the requested value is used as-is.
1134+
*
11121135
* <p>If the current {@link #getSinglePassLightBatchSize() batch size} exceeds the
11131136
* new maximum, it is clamped down to the new maximum. Otherwise the current
11141137
* batch size is left unchanged and will continue to auto-scale up to the new limit.
@@ -1117,6 +1140,16 @@ public int getMaxSinglePassLightBatchSize() {
11171140
*/
11181141
public void setMaxSinglePassLightBatchSize(int maxSinglePassLightBatchSize) {
11191142
this.maxSinglePassLightBatchSize = Math.max(maxSinglePassLightBatchSize, 1);
1143+
// Clamp to a hardware-safe value.
1144+
// Each light uses 3 vec4 uniforms in g_LightData; reserve 1/4 of the
1145+
// fragment uniform budget for other shader parameters (material params,
1146+
// transforms, etc.).
1147+
Integer fragUniformVecs = renderer.getLimits().get(Limits.FragmentUniformVectors);
1148+
if (fragUniformVecs != null && fragUniformVecs > 0) {
1149+
int reservedUniforms = Math.max(fragUniformVecs / RESERVED_UNIFORM_FRACTION, 1);
1150+
int maxByHardware = Math.max((fragUniformVecs - reservedUniforms) / VEC4_UNIFORMS_PER_LIGHT, 1);
1151+
this.maxSinglePassLightBatchSize = Math.min(this.maxSinglePassLightBatchSize, maxByHardware);
1152+
}
11201153
if (singlePassLightBatchSize > this.maxSinglePassLightBatchSize) {
11211154
singlePassLightBatchSize = this.maxSinglePassLightBatchSize;
11221155
}

0 commit comments

Comments
 (0)