Am 07.09.2011 02:00, schrieb Stéphane Marchesin: > 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?
Well adjusting the ctx pointer seems like a hack, if the struct isn't supposed to be shared in the first place. That said I'm not really sure why pipe_sampler_view and pipe_surface actually have a context pointer in them, since they are only supposed to be used with the context in which they were created I think those shouldn't actually exist - surface_destroy and sampler_view_destroy will have context as a parameter, and if they aren't shared between contexts it's pointless to store the context pointer. Might be a relic from when those structs were created/destroyed using screen functions... Roland _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev