Page MenuHome

Workbench Engine: Add support for UDIM textures
AbandonedPublic

Authored by Lukas Stockner (lukasstockner97) on Dec 17 2019, 1:20 AM.

Details

Summary

This patch implements support for drawing UDIM textures in the
workbench engine.

This is done by splitting the mesh that is to be drawn according
to its UVs, similar to how it is already done for materials.

I'm not certain whether this is the best approach of handling this,
any suggestions are very welcome!

Diff Detail

Repository
rB Blender
Branch
split-draw (branched from master)
Build Status
Buildable 6032
Build 6032: arc lint + arc unit

Event Timeline

Note that the same material- and tile-based splitting can be used to avoid another current limitation: GPUs can only bind a limited amount of textures at once, and the current Eevee UDIM approach quickly runs into this limit.

With this, it would be possible to add an option there to use a similar splitting approach that lets us bind only one tile per image texture for each GPUBatch. A downside of that would be that procedural UV manipulation across tile borders would not work, but as far as I can tell that is no concern for UDIM workflows (and the option would let you choose between flexibility vs. many images).

I already hacked together a VERY quick-and-dirty version of this and while it works (painting 2 images with 48 tiles each), it's extremely hacky, leaks memory all over the place and generally makes it very obvious that I have no idea of the drawing code, so I don't think there's a point in sharing that.
Point is, it is technically possible - the rough idea was to essentially duplicate the shgroup in material_opaque to get a copy for each tile, set a different tile override for each copy, then draw the individual pieces with "their" shgroup. By creating a new version of DRW_UNIFORM_TEXTURE that respects the override in draw_update_uniforms, this was able to switch textures on the fly just as needed.

Note that the same material- and tile-based splitting can be used to avoid another current limitation: GPUs can only bind a limited amount of textures at once, and the current Eevee UDIM approach quickly runs into this limit.

Can UDIM tiles be of different sizes?

  • If not we can use Texture2DArrays which have a limit of 256 layers.
  • If yes, can we force them to share the same size? use the maximum size? the minimum size?

I don't think we should try to split the mesh into different parts. Why can't you just use the uv float position to compute what tile to use in shader?

Why can't you just use the uv float position to compute what tile to use in shader?

Would be possible (and already happens, see node_tex_tile_map), but unfortunately they can be of different size (and currently even stuff like float/byte can be mixed, but I don't think we need to keep supporting that). Extending to maximum size could work, but might cause lots of memory overhead if you have e.g. ten 2k and one 8k tile. Maybe something like one texture array per different size, but that might get tricky to coordinate.

Extending to maximum size could work, but might cause lots of memory overhead if you have e.g. ten 2k and one 8k tile. Maybe something like one texture array per different size, but that might get tricky to coordinate.

With a UDIM texture, you also bind a descriptor 1D (or even 2D) texture that has the layer id and texture id to sample from. This would be your tricky part.
Issue would be performance because of the dependant texture reads but I doubt this would be a big problem since all the accesses would be coherent. Need to be tested and profiled.

Hm, we'd need a bit of logic to handle keeping the 2D arrays up to date when tiles change, for partial updates during painting etc., but it should work.
We'd still be limited a bit (e.g., if your texture limit is 24 and you are mixing four different sizes, you could have six different textures in one shader), but that would be a much smaller limitation.
Just to be clear, are you only talking about Eevee or also about the Workbench engine? If it's the former, we'd need to keep both regular textures for WB as well as Array textures for Eevee, which is not great for memory usage and complexity.

I did a first overview of the patch. There seems to be more ways to handle this. This patch is straight forward (conservative), but adds overhead during drawing and in the draw cache. As workbench uses at max a single texture and uv coordinates we could also investigate on adding the udim index (encoded as texture index) to a vbo and solve it in the shader. (as discussed above).

source/blender/draw/engines/workbench/workbench_deferred.c
911

Is this an limitation of the UDIM implementation?

Jeroen Bakker (jbakker) resigned from this revision.Wed, Jan 15, 8:12 AM

Sorry for not clearly marking that this patch is obsolete now that we have D6456, I hope you didn't spend too much time on the review :/