diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-09-30 22:18:32 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-09-30 22:18:32 +0400 |
commit | b466286c3e0e64860299a4737b9cb13c8fc15618 (patch) | |
tree | 8fd9918ecb93eb8ba44eab113360f62efe1f18d6 /source/blender/blenkernel/intern/image.c | |
parent | 727745bd49592e1b90f0ce9cb78556404ba518ca (diff) |
Render & Compositing Thread Fixes
* Rendering twice or more could crash layer/pass buttons.
* Compositing would crash while drawing the image.
* Rendering animations could also crash drawing the image.
* Compositing could crash
* Starting to rendering while preview render / compo was
still running could crash.
* Exiting while rendering an animation would not abort the
renderer properly, making Blender seemingly freeze.
* Fixes theoretically possible issue with setting malloc
lock with nested threads.
* Drawing previews inside nodes could crash when those nodes
were being rendered at the same time.
There's more crashes, manipulating the scene data or undo can
still crash, this commit only focuses on making sure the image
buffer and render result access is thread safe.
Implementation:
* Rather than assuming the render result does not get freed
during render, which seems to be quite difficult to do given
that e.g. the compositor is allowed to change the size of
the buffer or output different passes, the render result is
now protected with a read/write mutex.
* The read/write mutex allows multiple readers (and pixel
writers) at the same time, but only allows one writer to
manipulate the data structure.
* Added BKE_image_acquire_ibuf/BKE_image_release_ibuf to access
images being rendered, cases where this is not needed (most
code) can still use BKE_image_get_ibuf.
* The job manager now allows only one rendering job at the same
time, rather than the G.rendering check which was not reliable.
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 9953540bbcf..09d150341b2 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1564,15 +1564,22 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) return rpass; } -RenderResult *BKE_image_get_renderresult(struct Scene *scene, Image *ima) +RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, Image *ima) { if(ima->rr) return ima->rr; - if(ima->type==IMA_TYPE_R_RESULT) - return RE_GetResult(RE_GetRender(scene->id.name)); + else if(ima->type==IMA_TYPE_R_RESULT) + return RE_AcquireResultRead(RE_GetRender(scene->id.name)); return NULL; } +void BKE_image_release_renderresult(struct Scene *scene, Image *ima) +{ + if(ima->rr); + else if(ima->type==IMA_TYPE_R_RESULT) + RE_ReleaseResult(RE_GetRender(scene->id.name)); +} + /* after imbuf load, openexr type can return with a exrhandle open */ /* in that case we have to build a render-result */ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) @@ -1873,16 +1880,25 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) /* showing RGBA result itself (from compo/sequence) or like exr, using layers etc */ /* always returns a single ibuf, also during render progress */ -static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) +static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_r) { Render *re= NULL; RenderResult *rr= NULL; + /* if we the caller is not going to release the lock, don't give the image */ + if(!lock_r) + return NULL; + if(iuser && iuser->scene) { re= RE_GetRender(iuser->scene->id.name); - rr= RE_GetResult(re); + rr= RE_AcquireResultRead(re); + + /* release is done in BKE_image_release_ibuf using lock_r */ + *lock_r= re; } - if(rr==NULL) return NULL; + + if(rr==NULL) + return NULL; if(RE_RenderInProgress(re)) { ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); @@ -1893,6 +1909,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, IB_rect, 0); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } + return ibuf; } else { @@ -1907,7 +1924,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) pass= (iuser)? iuser->pass: 0; /* this gives active layer, composite or seqence result */ - RE_GetResultImage(RE_GetRender(iuser->scene->id.name), &rres); + RE_AcquireResultImage(RE_GetRender(iuser->scene->id.name), &rres); rect= (unsigned int *)rres.rect32; rectf= rres.rectf; dither= iuser->scene->r.dither_intensity; @@ -1954,10 +1971,14 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf->zbuf_float= rres.rectz; ibuf->flags |= IB_zbuffloat; ibuf->dither= dither; - + + RE_ReleaseResultImage(re); + ima->ok= IMA_OK_LOADED; return ibuf; } + + RE_ReleaseResultImage(re); } return NULL; @@ -2011,8 +2032,9 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame } /* Checks optional ImageUser and verifies/creates ImBuf. */ -/* returns ibuf */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +/* use this one if you want to get a render result in progress, + * if not, use BKE_image_get_ibuf which doesn't require a release */ +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf= NULL; float color[] = {0, 0, 0, 1}; @@ -2028,6 +2050,9 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. * That means, the last two steps must be, 1) add the ibuf to the list and * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ + + if(lock_r) + *lock_r= NULL; /* quick reject tests */ if(ima==NULL) @@ -2103,8 +2128,9 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) } else if(ima->source == IMA_SRC_VIEWER) { if(ima->type==IMA_TYPE_R_RESULT) { - /* always verify entirely */ - ibuf= image_get_render_result(ima, iuser); + /* always verify entirely, and potentially + returns pointer to release later */ + ibuf= image_get_render_result(ima, iuser, lock_r); } else if(ima->type==IMA_TYPE_COMPOSITE) { /* Composite Viewer, all handled in compositor */ @@ -2126,6 +2152,17 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) return ibuf; } +void BKE_image_release_ibuf(Image *ima, void *lock) +{ + /* for getting image during threaded render, need to release */ + if(lock) + RE_ReleaseResult(lock); +} + +ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +{ + return BKE_image_acquire_ibuf(ima, iuser, NULL); +} void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) { |