On Tue, 22 Sep 2026 23:16:36 GMT, Nir Lisker <[email protected]> wrote:

> Removes unnecessary GPU uploads. There are upload 7 calls (2 
> `SetVertexShaderConstantF` and 5 `SetPixelShaderConstantF`) that are called 
> per mesh per frame even when the lights affecting these nodes are unchanged.
> 
> **History**
> There were 3 uploads per mesh per frame: position, color, and ambient color. 
> After the addition of attenuation and light types, 4 additional uploads per 
> mesh per frame were added: attenuation, range, spotlight factors, and 
> direction. This resulted in an FPS hit. All 7 calls are now called only per 
> frame, so some of the FPS loss from the additional 4 uploads is recuperated, 
> plus a "retroactive" FPS recuperation from the initial 3 uploads.
> 
> **Mechanism**
> The constant registers retain their values throughout the context's 
> lifetime*, so by caching the lights in the context, the per mesh calls are 
> eliminated, leaving only the per frame calls. Cache invalidation happens on 
> changes in the device, and cache misses happen when a node is affected by 
> different lights. The scene will always override the registers, so 1 call per 
> frame is needed to upload them for the 3D rendering. More nodes affected by 
> different lights will causes more cache misses (uploads), and it depends on 
> the submission order of the nodes to the renderer.
> 
> **Results**
> Using the 3DLighting application, I measured a ~20% increase in FPS in 5k 
> `MeshView` tests, both in the single animation and the many animation modes. 
> Some tests with low N showed even a 30% or 40% increases, but are not as 
> trustworthy. These are the result of a flat per-mesh cost drop (~0.1 
> microseconds per mesh on my setup).
> The number of lights in the scene is irrelevant since 3 lights are sent to 
> the context in any case. This was confirmed in measurements.
> 
> Removal of the unneeded (per frame) render calls already on the Java side via 
> the dirty bits mechanism could be a future enhancement that affects all the 
> pipelines.
> 
> * <sub>A "discovery" I made only recently.</sub>
> 
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

In Metal also we set light constants in every renderMeshView call.
We set light constants and material data in same construct, so if we want to 
set light constants only once per encoder, we need little bit of refactoring. 
But as seen in this D3D change, it would be better to have similar change in 
Metal also.

Regarding change present in D3D9, the change looks good to me. I only have a 
small concern.

I see that we use `SetPixelShaderConstantF` in D3DShader.setConstantsF() also. 
Any float setConstant/setConstants call can reach D3DShader.setConstantsF() and 
if it happens in series of draw calls like: 3D draw -> Failed 2D draw but 
successful D3DShader.setConstantsF() -> again 3D draw.

The second 3D draw will not invalidate the light cache, so it will use wrong 
light data.
Its better if we invalidate the light constants when we have a 
D3DShader.setConstantsF() call as a safe guard.

But i don't see it as a blocker, because it would be difficult to hit the "3D 
draw -> Failed 2D draw but successful D3DShader.setConstantsF() -> again 3D 
draw" scenario.

-------------

PR Comment: https://git.openjdk.org/jfx/pull/2319#issuecomment-6143531374

Reply via email to