I didn't follow Denoising develop for a while so I'm quite confused now and my thoughts goes totally wrong direction.
I don't have a solution for you ... so probably someone can push it forward.
Viewport vs Render result is quite different
Test_Threshold 0.01, Samples 400, without / with denoiser
Upper row - Viewport
Bottom row - Render
It is a segment on left side of camera view where is structure softer (than on right side) so clearly visible what damage denoiser generates. Viewport at 400 samples already produce visible structure, but Output render not even signal.
Here same only with Samples 1000 ... Even for Viewport it seems already solved for Denoiser ...
Render is still completely vanished ... ???
Viewport is using Automatic, Render is using OpenImageDenoise solver, but even if I switch Viewport to OID or Render I switch to use Passes only Albedo (without Normal) the result is same.
Expectations - more samples = better denoised result is OK. 1000 samples seems to be fine for Viewport. What is really weird for me is the difference in Render result. The only one thing that came to my mind is they use different Light Path setup ...?
If I take sample from right side of camera view I can't see differences in structure above 400 samples and even without denoiser it looks clear.
- to Duplicate lights it is better to use Alt+D, like that all lights use the same Data, changing values of one light is shared with all light objects.
- also for such project is probably easier to distribute lights by plane with Array modifier, Parent Light to Plane and enable under Object Properties > Instancing
- I was wrong with Normal pass to try fake it in compositor, Normal pass takes into account a geometry, not a texture.
Under note - texture itself is quite sensitive for moire artefacts, would be hard to care right anti-aliasing ...
Restore Texture in Compositor
You can try to keep lower samples and map texture in compositor with MapUV node. Under scene enable UV pass. To repeat texture use node tree bellow. Downside of this - render and texture has to be the same proportions ... or someone smarter has to enhance this :)
Originaly mentioned here, there it works for also rectangle vs square, but there it is used just for flat image.