zink: track program usages for each shader
when shaders are created and destroyed in large numbers, the same pointers get reused for different shaders, which can lead to bad lookups in the program_cache hash table.
now each shader tracks its program usage to automatically remove itself from that program in order to avoid hash collisions
fixes #3053 (closed)