diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/engines/image/image_engine.c | 61 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_edit.c | 10 | ||||
-rw-r--r-- | source/blender/render/RE_pipeline.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/engine.c | 11 | ||||
-rw-r--r-- | source/blender/render/intern/pipeline.c | 1 | ||||
-rw-r--r-- | source/blender/render/intern/render_result.c | 65 | ||||
-rw-r--r-- | source/blender/render/intern/render_result.h | 2 |
7 files changed, 100 insertions, 52 deletions
diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c index 438c95118ef..b4c0ade380e 100644 --- a/source/blender/draw/engines/image/image_engine.c +++ b/source/blender/draw/engines/image/image_engine.c @@ -115,33 +115,48 @@ static void space_image_gpu_texture_get(Image *image, BKE_image_multiview_index(image, &sima->iuser); } - if (ibuf) { - const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf); - if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { - if (ibuf->zbuf) { - BLI_assert_msg(0, "Integer based depth buffers not supported"); - } - else if (ibuf->zbuf_float) { - *r_gpu_texture = GPU_texture_create_2d( - __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float); - *r_owns_texture = true; - } - else if (ibuf->rect_float && ibuf->channels == 1) { - *r_gpu_texture = GPU_texture_create_2d( - __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float); - *r_owns_texture = true; - } + if (ibuf == NULL) { + return; + } + + if (ibuf->rect == NULL && ibuf->rect_float == NULL) { + /* This codepath is only supposed to happen when drawing a lazily-allocatable render result. + * In all the other cases the `ED_space_image_acquire_buffer()` is expected to return NULL as + * an image buffer when it has no pixels. */ + + BLI_assert(image->type == IMA_TYPE_R_RESULT); + + float zero[4] = {0, 0, 0, 0}; + *r_gpu_texture = GPU_texture_create_2d(__func__, 1, 1, 0, GPU_RGBA16F, zero); + *r_owns_texture = true; + return; + } + + const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf); + if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { + if (ibuf->zbuf) { + BLI_assert_msg(0, "Integer based depth buffers not supported"); } - else if (image->source == IMA_SRC_TILED) { - *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf); - *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL); - *r_owns_texture = false; + else if (ibuf->zbuf_float) { + *r_gpu_texture = GPU_texture_create_2d( + __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float); + *r_owns_texture = true; } - else { - *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf); - *r_owns_texture = false; + else if (ibuf->rect_float && ibuf->channels == 1) { + *r_gpu_texture = GPU_texture_create_2d( + __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float); + *r_owns_texture = true; } } + else if (image->source == IMA_SRC_TILED) { + *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf); + *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL); + *r_owns_texture = false; + } + else { + *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf); + *r_owns_texture = false; + } } static void space_node_gpu_texture_get(Image *image, diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 169dafcb8d0..a95189a303f 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -139,8 +139,10 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock, int tile) ImBuf *ibuf; if (sima && sima->image) { + const Image *image = sima->image; + #if 0 - if (sima->image->type == IMA_TYPE_R_RESULT && BIF_show_render_spare()) { + if (image->type == IMA_TYPE_R_RESULT && BIF_show_render_spare()) { return BIF_render_spare_imbuf(); } else @@ -152,6 +154,12 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock, int tile) } if (ibuf) { + if (image->type == IMA_TYPE_R_RESULT && ibuf->x != 0 && ibuf->y != 0) { + /* Render result might be lazily allocated. Return ibuf without buffers to indicate that + * there is image buffer but it has no data yet. */ + return ibuf; + } + if (ibuf->rect || ibuf->rect_float) { return ibuf; } diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h index 4534c86f7f7..cd839385bfb 100644 --- a/source/blender/render/RE_pipeline.h +++ b/source/blender/render/RE_pipeline.h @@ -155,6 +155,8 @@ typedef struct RenderResult { char *error; struct StampData *stamp_data; + + bool passes_allocated; } RenderResult; typedef struct RenderStats { diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c index 75b3f2db249..1510587502b 100644 --- a/source/blender/render/intern/engine.c +++ b/source/blender/render/intern/engine.c @@ -212,6 +212,8 @@ static RenderResult *render_result_from_bake(RenderEngine *engine, int x, int y, RenderPass *primitive_pass = render_layer_add_pass(rr, rl, 4, "BakePrimitive", "", "RGBA"); RenderPass *differential_pass = render_layer_add_pass(rr, rl, 4, "BakeDifferential", "", "RGBA"); + render_result_passes_allocated_ensure(rr); + /* Fill render passes from bake pixel array, to be read by the render engine. */ for (int ty = 0; ty < h; ty++) { size_t offset = ty * w * 4; @@ -328,6 +330,7 @@ RenderResult *RE_engine_begin_result( /* can be NULL if we CLAMP the width or height to 0 */ if (result) { render_result_clone_passes(re, result, viewname); + render_result_passes_allocated_ensure(result); RenderPart *pa; @@ -400,6 +403,14 @@ void RE_engine_end_result( return; } + if (!re->result->passes_allocated) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if (!re->result->passes_allocated) { + render_result_passes_allocated_ensure(re->result); + } + BLI_rw_mutex_unlock(&re->resultmutex); + } + /* merge. on break, don't merge in result for preview renders, looks nicer */ if (!highlight) { /* for exr tile render, detect tiles that are done */ diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 479ad9209f0..9ef52b4bf41 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -354,6 +354,7 @@ RenderResult *RE_AcquireResultWrite(Render *re) { if (re) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + render_result_passes_allocated_ensure(re->result); return re->result; } diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index 091f5964291..c29ab342ed7 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -222,7 +222,6 @@ RenderPass *render_layer_add_pass(RenderResult *rr, { const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name); - size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels; rpass->channels = channels; rpass->rectx = rl->rectx; @@ -249,33 +248,6 @@ RenderPass *render_layer_add_pass(RenderResult *rr, } } - /* Always allocate combined for display, in case of save buffers - * other passes are not allocated and only saved to the EXR file. */ - if (rl->exrhandle == NULL || STREQ(rpass->name, RE_PASSNAME_COMBINED)) { - float *rect; - int x; - - rpass->rect = MEM_callocN(sizeof(float) * rectsize, name); - if (rpass->rect == NULL) { - MEM_freeN(rpass); - return NULL; - } - - if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { - /* initialize to max speed */ - rect = rpass->rect; - for (x = rectsize - 1; x >= 0; x--) { - rect[x] = PASS_VECTOR_MAX; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_Z)) { - rect = rpass->rect; - for (x = rectsize - 1; x >= 0; x--) { - rect[x] = 10e10; - } - } - } - BLI_addtail(&rl->passes, rpass); return rpass; @@ -316,6 +288,8 @@ RenderResult *render_result_new( rr->do_exr_tile = true; } + rr->passes_allocated = false; + render_result_views_new(rr, &re->r); /* check renderdata for amount of layers */ @@ -484,6 +458,40 @@ RenderResult *render_result_new( return rr; } +void render_result_passes_allocated_ensure(RenderResult *rr) +{ + LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) { + LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) { + if (rl->exrhandle != NULL && !STREQ(rp->name, RE_PASSNAME_COMBINED)) { + continue; + } + + if (rp->rect != NULL) { + continue; + } + + const size_t rectsize = ((size_t)rr->rectx) * rr->recty * rp->channels; + rp->rect = MEM_callocN(sizeof(float) * rectsize, rp->name); + + if (STREQ(rp->name, RE_PASSNAME_VECTOR)) { + /* initialize to max speed */ + float *rect = rp->rect; + for (int x = rectsize - 1; x >= 0; x--) { + rect[x] = PASS_VECTOR_MAX; + } + } + else if (STREQ(rp->name, RE_PASSNAME_Z)) { + float *rect = rp->rect; + for (int x = rectsize - 1; x >= 0; x--) { + rect[x] = 10e10; + } + } + } + } + + rr->passes_allocated = true; +} + void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname) { RenderLayer *rl; @@ -1243,6 +1251,7 @@ void render_result_exr_file_end(Render *re, RenderEngine *engine) render_result_free_list(&re->fullresult, re->result); re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); re->result->stamp_data = stamp_data; + render_result_passes_allocated_ensure(re->result); BLI_rw_mutex_unlock(&re->resultmutex); LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) { diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h index 7732c113700..1fc64a4ea97 100644 --- a/source/blender/render/intern/render_result.h +++ b/source/blender/render/intern/render_result.h @@ -55,6 +55,8 @@ struct RenderResult *render_result_new(struct Render *re, const char *layername, const char *viewname); +void render_result_passes_allocated_ensure(struct RenderResult *rr); + struct RenderResult *render_result_new_from_exr( void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); |