2011/9/6 Roland Scheidegger <srol...@vmware.com>: > Am 07.09.2011 00:01, schrieb Stéphane Marchesin: >> 2011/9/3 Jose Fonseca <jfons...@vmware.com>: >>> >>> >>> ----- Original Message ----- >>>> 2011/9/2 Stéphane Marchesin <stephane.marche...@gmail.com>: >>>>> 2011/9/2 Jose Fonseca <jfons...@vmware.com>: >>>>>> ----- Original Message ----- >>>>>>> Hi, >>>>>>> >>>>>>> While debugging some code I ran across the following situation: >>>>>>> >>>>>>> - pipe_context c1 is created >>>>>>> - pipe_surface s1 is created >>>>>>> - strb-> surface is set to s1 (s1's refcount goes up) >>>>>>> - pipe_context c1 is destroyed >>>>>>> - strb is destroyed >>>>>>> - strb->surface is destroyed (so s1's refcount is now 0 and we >>>>>>> want >>>>>>> to >>>>>>> destroy it) >>>>>>> >>>>>>> At that point s1 references c1 which is not available any more, >>>>>>> so >>>>>>> when we try to call ctx->surface_destroy to destroy s1 we crash. >>>>>>> >>>>>>> We discussed this a bit on IRC, and we agreed that the proper >>>>>>> solution, since surfaces outlive their context, is to make >>>>>>> surfaces >>>>>>> screen-bound instead. I'm going to implement that unless someone >>>>>>> objects. >>>>>>> >>>>>>> As a side note, the same issue will happen with sampler_views, so >>>>>>> it'll get a similar fix. >>>>>> >>>>>> Sampler views and surfaces were previously objects bound to >>>>>> screen, and we changed that because of poor multithreading >>>>>> semantics. Per-context sampler views / render targets actually >>>>>> matches the 3D APIs semantics better, so I don't think that >>>>>> reverting is the solution. >>>>>> >>>>>> It looks to me that the issue here is that pipe_context should not >>>>>> be destroyed before the surfaces. strb->surface should only be >>>>>> used by one context, and should be destroyed before that context >>>>>> is destroyed. >>>>>> >>>>>> IIUC, strb matches GL renderbuffer semantics and can be shared by >>>>>> multiple context. If so, strb is treating pipe_surfaces as a >>>>>> entity shareable by contexts when really shouldn't. >>>>>> >>>>>> The solution is: >>>>>> - strb can only have pipe_resources, plus the key for the surface >>>>>> (face, level, etc) >>>>>> - the pipe_surfaces that are derived should be stored/cached in >>>>>> the GLcontext. >>>>>> - when the GLcontext / pipe_context is being destroy, the pipe >>>>>> surfaces can be destroyed before >>>>>> >>>>> >>>>> I don't understand some of it. From what I see, it should be >>>>> enough, >>>>> whenever strb binds a surface, to add a pointer to this strb to a >>>>> list of strb's to the pipe_context. By doing that, we would be able >>>>> to >>>>> unbind the surfaces from the strb before we destroy the context. >>>>> However, pipe_context structures can't reference gl structures, so >>>>> how >>>>> would you solve that? >>>>> >>>> >>>> Alright, maybe I'm too tired, I just have to put it in strb... My >>>> other questions still stand though :) >>>> >>>> Stéphane >>>> >>>> >>>>> Also, what difference does it make if strb's only have >>>>> pipe_resources? >>> >>> Pipe resources can be shared between contexts, therefore they should not >>> refer context or context data. >>> So it is always safe to destroy pipe_resources pipe_contexts on any order. >>> >>> Using your example above, if you replace surface "s1" with resource "r1", a >>> reference from r1 to c1 would be violating the semantics. >>> >>>>> And why do I need a key? >>> >>> "key" is a bad name perhaps. Unless the resource is always a single level >>> 2d texture, if we replace the strb->surface with a strb->resource, we will >>> need to specify separately which face/level is sought. >>> >>>>> This all is definitely more complex than it should be. >>> >>> May be I'm not understanding what you were proposing. When you said that >>> >>> "the proper solution, since surfaces outlive their context, is to make >>> surfaces screen-bound instead" >>> >>> I interpreted this statement as moving the pipe_context::create_surface >>> method to pipe_screen::create_surface. Was this really your plan or did you >>> meant something else? >>> >>> Because, my understanding is that it should be the other way around: when >>> we moved the create_surface method from pipe_screen to pipe_context, we >>> forgot to fix the st_renderbuffer code to do this properly. >>> >>> >>> >>> The fix I proposed may seem a bit complex, but keeping pipe_surfaces as >>> context objects actually helps pipe drivers that put derived data in >>> pipe_surfaces to be much simpler, as they no longer need complicated >>> locking to be thread safe -- the state tracker guarantees that >>> pipe_surfaces belong to that context, and that context alone. >>> >>> That is, moving stuff all into the screen sounds simple at first, but then >>> it becomes a serious nightmare to make it thread safe. >>> >>> >>> >>> Note that if st_renderbuffer can't be shared between GL contexts, then the >>> solution can be much simpler: all we need to do is ensure that the surfaces >>> are destroyed before the context. I haven't looked at the Mesa state >>> tracker code in a while, so I'm a bit rusty in this regard. >>> >>> ARB_framebuffer_object says that framebuffer objects are per-context, but >>> renderbuffer objects like textures can be shared between contexts. So when >>> one looks at st_renderbuffer definition: >>> >>> /** >>> * Derived renderbuffer class. Just need to add a pointer to the >>> * pipe surface. >>> */ >>> struct st_renderbuffer >>> { >>> struct gl_renderbuffer Base; >>> struct pipe_resource *texture; >>> struct pipe_surface *surface; /* temporary view into texture */ >>> struct pipe_sampler_view *sampler_view; >>> enum pipe_format format; /** preferred format, or >>> PIPE_FORMAT_NONE */ >>> GLboolean defined; /**< defined contents? */ >>> >>> /** >>> * Used only when hardware accumulation buffers are not supported. >>> */ >>> boolean software; >>> size_t stride; >>> void *data; >>> >>> struct st_texture_object *rtt; /**< GL render to texture's >>> texture */ >>> int rtt_level, rtt_face, rtt_slice; >>> >>> /** Render to texture state */ >>> struct pipe_resource *texture_save; >>> struct pipe_surface *surface_save; >>> struct pipe_sampler_view *sampler_view_save; >>> }; >>> >>> There are several pipe_context specific state that shouldn't be here: all >>> pipe_surface and pipe_sampler_view objects, which can potentially be used >>> by a context other than the context that created them. Those pointer >>> should be kept either in a framebuffer object, and/or the GL context: >>> created/destroyed as needed, or maybe cached for performance. >> >> Ok, so those things "shouln't be here", but I still don't get what you >> want to replace that pipe_surface member with for example. You need >> the format/size in many places, how is that going to fly? Access them >> through the context somehow? > > Note that there's actually lots of unused stuff in there. > surface_save, sampler_view_save (as well as texture_save though this is > not a problem here) are never used anywhere so can trivially go. > sampler_view in there is probably a mistake too it is only used for ref > counting purposes outside of a (unused - even says so in a comment) > function (st_get_renderbuffer_sampler_view), and I can't see why this > would be needed. Probably a leftover from earlier code. > So this leaves only the surface pointer as problematic. > I'm not quite sure where you'd want to store the pipe_surface, but I > think all the information you need to (re)create it can already be > extracted from st_renderbuffer. You could for instance create a cache of > surfaces in st_context maybe. Obviously this means if you share a > st_renderbuffer you have to create "identical" pipe_surfaces in each > context (should be pretty light-weight, though obviously could be a > problem for some less capapble hw if the driver needs to make a copy of > the actual resource data, in that case the driver probably would need to > make sure it can recognize such cases and do deferred destruction of the > copied data but this is a problem anyway). > Or you could just put the surface pointer into another struct instead > (which would also contain a pointer to the strb) and use that throughout > most of the code (except for sharing, of course).
How is that different from updating the ctx pointer in pipe_surface to the to the context still using the strb after the old context vanishes? Stéphane _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev