A texture watched by its hashes is hashed by 4 KB pieces of video memory.
When only some of them changed, and nothing else (palette, stride), the
regions of the image those pieces are in are made again and the rest is
left: twiddled, planar, compressed (unless the codebook changed), paletted
and mipmapped textures down to their 8x8 level, up to 16 regions, while
they cover less than half of it. Vulkan makes them on the GPU over those
groups only (vkCmdDispatchBase) from just their bytes, or copies the rows
of a planar one; converted on the CPU, Vulkan, Direct3D 11 and 12 and
OpenGL upload just them. Direct3D's and OpenGL's decoders make the texture
whole; so do textures scaled up, dumped or replaced.
tools/rend/texconv_test.sh part holds every update of textures of each
kind, written a few bytes at a time, to what a full upload makes, on the
CPU and through the kernel's text.
A texture that changes often is watched by a hash of its bytes in video
memory, and a render's parse asks for it for every polygon that uses it.
It is hashed the first time in a render, and again in that render only
after the render thread has collected a write to video memory.
tools/rend/texconv_test.sh holds every request against what a full upload
makes, with video memory written between renders and in the middle of one,
and a texture asked for 300 times in a render to one hash.
sh tools/rend/texconv_test.sh
Every converter the texture cache has - each pixel format; twiddled,
compressed, planar, planar and compressed, paletted; to 16, 32 and 8
bits - is given the same bytes at five sizes, random ones and a ramp,
and a hash of what comes out is compared with what upstream flycast's
converters gave for those bytes (texconv_expected.txt, made by
building the same file in an upstream tree with -DUPSTREAM). 340
results, all the same.
The converters are pure functions, so this is also the gate for
rewriting them: whatever replaces them has to print the same file.