Currently whenever we use a render surface we render into a texture. We also always track damage on a per-RS basis. I think it'd be fine to simply not delete the texture unless it received damage or we are over/close to some memory limit, in the worst case it means that we don't free up the texture as quickly.
OK - the request from the UI people was mainly to be able to kill the layers that are underneath the "frozen" layer (which would cause more damage to happen). We don't necessarily need this for this particular case, but we'll need to change other parts of the UI to guarantee that we won't generate damage (e.g. freeze the renderer somehow).
Assigning to zlieber@ as a starter bug. He's going to work on a minor
refactor or two to get up to speed with workflow/codebase first --- so not
started, just assigned for now.
Changes in layers properties need to be divided into two groups: those that
change content of the target surface, and thereby invalidate any cached
quads, and those that don't. Currently we only have one boolean flag in the
layer, m_layerPropertyChanged. We need to add a second flag, named
m_layerSurfacePropertyChanged (NAME TBD) and set it in appropriate
operations instead of the other one.
2. Changes in CCDamageTracker
We need to change the semantics of m_currentDamageRect. If our surface's
owning layer did not change its property (m_layerPropertyChanged) and the
rest of the layers are spotless clean, then m_currentDamageRect will be
empty. ("Spotless" means none
of the two flags is set). If the rest is not spotless clean (just clean, or
dirty), m_currentDamageRect will describe the extent of the change.
Exception is the root surface, which will always be either dirty or
spotless - otherwise we'll end up with empty rootDamageRect.
3. Changes in CCRenderSurfaceDrawQuad
Each CCRenderSurfaceDrawQuad will now store a pointer to a render surface
that it represents. It will get the pointer in the constructor.
4. Changes in appendQuads
All quads are always appened, regardless of the m_currentDamageRect state
(as long as they are in the scissorRect). However, if the
m_currentDamageRect is empty, the surface quad gets an extra flag
- !m_contentsChanged. This flag will be later used for removing unneeded
render passes.
5. Changes in render passes
The culling of the extra passes will be done on the RenderPass level, after
it has been assembled. In the future, it will be done after the render
passes are combined with other passes in a different process.
The alg for the culling is as follows:
- Iterate through RenderPasses in the order OPPOSITE to drawing, i.e. start
from the root.
- For each CCRenderSurfaceDrawQuad, do the following
- If its contents haven't changed AND the we have a valid texture:
- Recursively remove all render passes that contribute to this surface.
For each render pass being removed, find all CCRenderSurfaceDrawQuads in it
and kill their render passes too. To find the render passes, search through
the entire list to find the one that has a same render surface pointer as
the CCRenderSurfaceDrawQuad.
It seems that not delete/creating the surface texture is a good start (~10%
reduction in time to draw a frame). Not binding and redrawing the contents
of the surface texture adds to this (~10% further reduction).
But the animation is still below 30 fps. There is something else quite
costly in this animation, maybe it is just the blending? We don't have any
data pointing out anything particular yet.
To explain away the slow texture creation, piman had some hints to start
with. GLES2DecoderImpl::ClearLevel is going to clear new textures and does
this by mallocing and memsetting a 4M block of memory, then doing
glTexSubImage2D into the texture in 4mb blocks. I'm not sure what we can do
better in this function, maybe not malloc/memset and just keep the 0s
around? Maybe use glClear? </noobface>
In the case of the browser renderer, perhaps we can consider it trusted and
not clear the texture on creation. In ubercomp that would drop the cost on
all surface textures (yay).
@zlieber : Would you mind giving an update on the current status of this
bug? Looks like at least some of the proposed work has been done. What's
left to do here and is performance still a problem?
Zeev's not working on graphics any more, so I can fill in.
Comment #26/27 give a bit of a summary where this is at. It has dropped off
the radar because the UI stopped animating with opacity < 1 to avoid using
render surfaces.
We are now currently caching surface textures when they are not
dirtied/resized. If the UI wants to do such an animation again, we're going
to have to do some profiling to determine what is the bottleneck.
So, right now, we have no pressure to make this any better and things
are "good enough". If someone would like to make some test cases of bad
situations I'm sure they can find some data to motivate and demonstrate
improvements.