For each Texture that is referenced by a Material, there will be multiple uploads (glTexSubImage2D) of the same content.
What should happen is that for every Frontend QNode that subclasses QAbstractTextureImage, a QBackendNode is created of type RenderTextureImage. When after the RenderTextureImage is created, it is updated from its frontend peer, which then adds a handle to the texture image data to the associated backend RenderTexture. For each of these handles, there will occur a texture upload on the next frame.
What instead ends up happening is that initially everything works as expected:
(QTextureImage) cube1Texture -> RenderTextureImage -> (RenderTexture)addTextureImageData
(QTextureImage) cube2Texture -> RenderTextureImage -> (RenderTexture)addTextureImageData
Which would mean 1 texture upload for each texture when appropriate.
But each QTextureImage QNode gets cloned an additional 4 times, and the next time the scene is traversed and backend peers are made for the new node copies. Each time creating a new RenderTextureImage backend node and associated an additional copy of the texture data with the RenderTexture. So for each clone made we get an additional upload. For more complex scenes than this test it can load to crazy numbers (I've seen up to 49 uploads per texture).
Attached is an example that demonstrates this bug and an apitrace file demonstrating which OpenGL calls are made. The example has 2 materials, each with it's own diffuse texture. In Frame1, for each texture, there are 5 texture upload sequences, whereas 1 for each would be sufficient.