GraphicsBuffer and interpolation

One really neat side effect of using image textures for passing Vector3 data into a VFX Graph was free interpolation. Indexing the texture with a float usually did roughly what you would want positional interpolation to do.

Am I right in thinking there’s no interpolation with GraphicsBuffers?

If so - any guesses if doing my own lerping in the graph would be more or less performant than the overhead associated with sticking with textures? (I’m presuming here that a there is an advantage with GraphicsBuffers. That assumption might be incorrect)

And finally - would this be a useful feature to add?

@VladVNeykov - sorry to ping you but do you have an opinion on this?

Hi @andybak ,

You are correct, there’s no interpolation currently, but yes, I agree it would be useful as the workaround is a bit cumbersome:

(courtesy of @PaulDemeulenaere )

For the performance, it should be almost equivalent though, so this should be a feasible workaround. Thanks for the feedback Andy, we’ll jot this down as an improvement request and take a look! :slight_smile:

I think just bundling the above as a subgraph in the “Samples” would be helpful.

(Talking of which - those Samples are crazy useful but it’s hard to grok what their uses are. Any chance of a bit of documentation?)

Sorry - can I ask for clarification on your comment on “performance”?

I’m still weighing up Texture vs GraphicsBuffers. Are you saying “GraphicsBuffer + manual lerping” is as performant as Textures? Does loading a texture have much performance overhead vs a graphics buffer? (assuming the data comes from C# and not from a compute shader)

Other than that the only downside of textures is the clunky extra code needed but I can live with that. I’m tempted to stick with textures - at least for any case where I might want interpolation.

There isn’t a simple answer.

The sampling of a GraphicsBuffer is actually a Load in a StructuredBuffer.

Let’s take the theoretical results from NVidia Ampere in this performance test and assuming your sampling is linear (for instance, based on the ParticleId), we have:

StructuredBuffer<float4>.Load linear: 9.839ms

versus

Texture2D<RGBA32F>.Sample(bilinear) linear: 49.592ms

However, it’s not fair, the Ampere texture sampling is quater rate with RGBA32F and the sampling of a Texture2D requires twice more data than a Texture1D to process the bilinear filter.
Furthermore, even if the loading of the next adress can be virtually free, the linear interpolation requires some additional computation.

If we are comparing the same result with Intel Iris, we have:

StructuredBuffer<float4>.Load linear: 868.643ms

versus

Texture2D<RGBA32F>.Sample(bilinear) linear: 918.780ms

These timings are almost equivalent.

In the end, theoretically, the sampling of GraphicsBuffer could be faster but I’m pretty sure there are platforms where the texture fetching is actually more efficient thanks to the optimized sampler interpolation.

I won’t expect a significative difference in one direction or the other with a real world case. I would advise you to use the simplest approach for your case, unless your targeted platform is really GPU bound, in that case, you will have to profile to adjust your decision.

Wow. That’s incredibly helpful. If anything it’s convinced me to switch to GraphicsBuffer unless I absolutely must have interpolation. And given that and the simple reusable subgraph that Vlad posted - I’ll probably switch for everything.