We need to rework the way that things are allocated in NIR. Everything is allocated using ralloc, the recursive memory allocator built into mesa. While using ralloc is fine, our use of memory contexts is less than stellar. Right now we allocate the shader by itself and then allocate everything else in the context of the shader. While this does mean that everything gets cleaned up when the entire shader is thrown away, it's far more coarse-grained than we'd like. It would be good if, for instance, freeing an instruction also freed any strings attached to it. What I would like to do is two things. First is to define a better allocation convention that is more granular and refactor the existing NIR code accordingly. Most of the constructor functions take a void* memory context. These should be changed to take whatever the appropreate parent type is to ensure that the convention is followed. I haven't thought it 100% of the way through, but I think it should be sufficient to have nir_shader, nir_function_impl, nir_register, nir_variable, and nir_instr as contexts. Everything else would be allocated in whatever the nearest context is. For example, the name string for a variable would go in the variable context, a list of instruction sources would go in the instruction context, etc. Instructions themselves would go in the context of the function in which they belong. One could make an argument for making a nir_block its own context and parenting instructions to their block but I think that's excessive and it will make it harder to move instructions around correctly. The second part of the project is to write a mark+sweep memory cleanup pass. We already have a pass like this in the old GLSL IR. The idea is to create a new context and reparent everything that's still reachable to the new context. You then throw the old context away and with it goes all of the stuff that was removed from the shader but not actually freed. The way this would work in NIR is as follows: First, we add a mem_ctx field to nir_function_impl and, instead of using the nir_function_impl as a context directly, create a plain memory context for the function implementation and the registers, instructions, etc. in it. Then we write a pass that, for each function, creates a new base context and uses ralloc_steal to reparent everything in the function to the new base context. Once everything has been reparented to the new context, we throw the old context away.
Ken did this a while ago.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.