Refactor: Use ImBuf to store passes in RenderResult #109788
|
@ -3987,12 +3987,9 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
|
|||
if (ima->rr) {
|
||||
RenderPass *rpass = BKE_image_multilayer_index(ima->rr, iuser);
|
||||
|
||||
if (rpass) {
|
||||
// printf("load from pass %s\n", rpass->name);
|
||||
ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
|
||||
ibuf->channels = rpass->channels;
|
||||
|
||||
IMB_assign_shared_float_buffer(ibuf, rpass->buffer.data, rpass->buffer.sharing_info);
|
||||
if (rpass && rpass->ibuf) {
|
||||
ibuf = rpass->ibuf;
|
||||
IMB_refImBuf(ibuf);
|
||||
|
||||
BKE_imbuf_stamp_info(ima->rr, ibuf);
|
||||
|
||||
|
@ -4295,15 +4292,12 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
|
|||
if (ima->rr) {
|
||||
RenderPass *rpass = BKE_image_multilayer_index(ima->rr, iuser);
|
||||
|
||||
if (rpass) {
|
||||
ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
|
||||
if (rpass && rpass->ibuf) {
|
||||
ibuf = rpass->ibuf;
|
||||
IMB_refImBuf(ibuf);
|
||||
|
||||
image_init_after_load(ima, iuser, ibuf);
|
||||
|
||||
IMB_assign_shared_float_buffer(ibuf, rpass->buffer.data, rpass->buffer.sharing_info);
|
||||
|
||||
ibuf->channels = rpass->channels;
|
||||
|
||||
BKE_imbuf_stamp_info(ima->rr, ibuf);
|
||||
|
||||
image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : IMA_NO_INDEX, 0);
|
||||
|
@ -4318,15 +4312,10 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
|
|||
/* always returns a single ibuf, also during render progress */
|
||||
static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_lock)
|
||||
{
|
||||
Render *re;
|
||||
RenderView *rv;
|
||||
RenderBuffer *combined_buffer;
|
||||
RenderByteBuffer *byte_buffer;
|
||||
ImBuf *pass_ibuf = nullptr;
|
||||
float dither;
|
||||
int channels, layer, pass;
|
||||
ImBuf *ibuf;
|
||||
int from_render = (ima->render_slot == ima->last_render_slot);
|
||||
int actview;
|
||||
const int from_render = (ima->render_slot == ima->last_render_slot);
|
||||
|
||||
if (!(iuser && iuser->scene)) {
|
||||
return nullptr;
|
||||
|
@ -4337,12 +4326,11 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
re = RE_GetSceneRender(iuser->scene);
|
||||
Render *re = RE_GetSceneRender(iuser->scene);
|
||||
|
||||
channels = 4;
|
||||
layer = iuser->layer;
|
||||
pass = iuser->pass;
|
||||
actview = iuser->view;
|
||||
const int layer = iuser->layer;
|
||||
const int pass = iuser->pass;
|
||||
int actview = iuser->view;
|
||||
|
||||
if (BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO)) {
|
||||
actview = iuser->multiview_eye;
|
||||
|
@ -4355,7 +4343,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
}
|
||||
else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) {
|
||||
rres = *(slot->render);
|
||||
rres.have_combined = ((RenderView *)rres.views.first)->combined_buffer.data != nullptr;
|
||||
rres.have_combined = ((RenderView *)rres.views.first)->ibuf != nullptr;
|
||||
}
|
||||
|
||||
if (!(rres.rectx > 0 && rres.recty > 0)) {
|
||||
|
@ -4380,12 +4368,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
|
||||
/* this gives active layer, composite or sequence result */
|
||||
if (rv == nullptr) {
|
||||
byte_buffer = &rres.byte_buffer;
|
||||
combined_buffer = &rres.combined_buffer;
|
||||
pass_ibuf = rres.ibuf;
|
||||
}
|
||||
else {
|
||||
byte_buffer = &rv->byte_buffer;
|
||||
combined_buffer = &rv->combined_buffer;
|
||||
pass_ibuf = rv->ibuf;
|
||||
}
|
||||
|
||||
dither = iuser->scene->r.dither_intensity;
|
||||
|
@ -4394,13 +4380,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
if (rres.have_combined && layer == 0) {
|
||||
/* pass */
|
||||
}
|
||||
else if (byte_buffer && byte_buffer->data && layer == 0) {
|
||||
/* rect32 is set when there's a Sequence pass, this pass seems
|
||||
* to have layer=0 (this is from image_buttons.c)
|
||||
* in this case we ignore float buffer, because it could have
|
||||
* hung from previous pass which was float
|
||||
*/
|
||||
combined_buffer = nullptr;
|
||||
else if (pass_ibuf && pass_ibuf->byte_buffer.data && layer == 0) {
|
||||
/* pass */
|
||||
}
|
||||
else if (rres.layers.first) {
|
||||
RenderLayer *rl = static_cast<RenderLayer *>(
|
||||
|
@ -4408,78 +4389,24 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
if (rl) {
|
||||
RenderPass *rpass = image_render_pass_get(rl, pass, actview, nullptr);
|
||||
if (rpass) {
|
||||
combined_buffer = &rpass->buffer;
|
||||
pass_ibuf = rpass->ibuf;
|
||||
if (pass != 0) {
|
||||
channels = rpass->channels;
|
||||
dither = 0.0f; /* don't dither passes */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
|
||||
if (pass_ibuf) {
|
||||
/* TODO(sergey): Perhaps its better to assign dither when ImBuf is allocated for the render
|
||||
* result. It will avoid modification here, and allow comparing render results with different
|
||||
* dither applied to them. */
|
||||
pass_ibuf->dither = dither;
|
||||
|
||||
/* make ibuf if needed, and initialize it */
|
||||
if (ibuf == nullptr) {
|
||||
ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, 0);
|
||||
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
|
||||
IMB_refImBuf(pass_ibuf);
|
||||
}
|
||||
|
||||
/* Set color space settings for a byte buffer.
|
||||
*
|
||||
* This is mainly to make it so color management treats byte buffer
|
||||
* from render result with Save Buffers enabled as final display buffer
|
||||
* and doesn't apply any color management on it.
|
||||
*
|
||||
* For other cases we need to be sure it stays to default byte buffer space.
|
||||
*/
|
||||
if (ibuf->byte_buffer.data != byte_buffer->data) {
|
||||
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
|
||||
IMB_colormanagement_assign_byte_colorspace(ibuf, colorspace);
|
||||
}
|
||||
|
||||
/* invalidate color managed buffers if render result changed */
|
||||
BLI_thread_lock(LOCK_COLORMANAGE);
|
||||
if (combined_buffer && (ibuf->x != rres.rectx || ibuf->y != rres.recty ||
|
||||
ibuf->float_buffer.data != combined_buffer->data))
|
||||
{
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
}
|
||||
|
||||
ibuf->x = rres.rectx;
|
||||
ibuf->y = rres.recty;
|
||||
ibuf->channels = channels;
|
||||
|
||||
imb_freerectImBuf(ibuf);
|
||||
|
||||
if (byte_buffer) {
|
||||
IMB_assign_shared_byte_buffer(ibuf, byte_buffer->data, byte_buffer->sharing_info);
|
||||
}
|
||||
else {
|
||||
IMB_assign_byte_buffer(ibuf, nullptr, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
}
|
||||
|
||||
if (combined_buffer) {
|
||||
IMB_assign_shared_float_buffer(ibuf, combined_buffer->data, combined_buffer->sharing_info);
|
||||
}
|
||||
else {
|
||||
IMB_assign_float_buffer(ibuf, nullptr, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
}
|
||||
|
||||
/* TODO(sergey): Make this faster by either simply referencing the stamp
|
||||
* or by changing both ImBuf and RenderResult to use same data type to
|
||||
* store metadata. */
|
||||
if (ibuf->metadata != nullptr) {
|
||||
IMB_metadata_free(ibuf->metadata);
|
||||
ibuf->metadata = nullptr;
|
||||
}
|
||||
BKE_imbuf_stamp_info(&rres, ibuf);
|
||||
|
||||
BLI_thread_unlock(LOCK_COLORMANAGE);
|
||||
|
||||
ibuf->dither = dither;
|
||||
|
||||
return ibuf;
|
||||
return pass_ibuf;
|
||||
}
|
||||
|
||||
static int image_get_multiview_index(Image *ima, ImageUser *iuser)
|
||||
|
|
|
@ -736,7 +736,7 @@ bool BKE_image_render_write_exr(ReportList *reports,
|
|||
/* Compositing result. */
|
||||
if (rr->have_combined) {
|
||||
LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
|
||||
if (!rview->combined_buffer.data) {
|
||||
if (!rview->ibuf || !rview->ibuf->float_buffer.data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -757,8 +757,8 @@ bool BKE_image_render_write_exr(ReportList *reports,
|
|||
float *output_rect =
|
||||
(save_as_render) ?
|
||||
image_exr_from_scene_linear_to_output(
|
||||
rview->combined_buffer.data, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
|
||||
rview->combined_buffer.data;
|
||||
rview->ibuf->float_buffer.data, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
|
||||
rview->ibuf->float_buffer.data;
|
||||
|
||||
for (int a = 0; a < channels; a++) {
|
||||
char passname[EXR_PASS_MAXNAME];
|
||||
|
@ -814,11 +814,14 @@ bool BKE_image_render_write_exr(ReportList *reports,
|
|||
const bool pass_half_float = half_float && pass_RGBA;
|
||||
|
||||
/* Color-space conversion only happens on RGBA passes. */
|
||||
float *output_rect =
|
||||
(save_as_render && pass_RGBA) ?
|
||||
image_exr_from_scene_linear_to_output(
|
||||
rp->buffer.data, rr->rectx, rr->recty, rp->channels, imf, tmp_output_rects) :
|
||||
rp->buffer.data;
|
||||
float *output_rect = (save_as_render && pass_RGBA) ?
|
||||
image_exr_from_scene_linear_to_output(rp->ibuf->float_buffer.data,
|
||||
rr->rectx,
|
||||
rr->recty,
|
||||
rp->channels,
|
||||
imf,
|
||||
tmp_output_rects) :
|
||||
rp->ibuf->float_buffer.data;
|
||||
|
||||
for (int a = 0; a < std::min(channels, rp->channels); a++) {
|
||||
/* Save Combined as RGBA or RGB if single layer save. */
|
||||
|
|
|
@ -59,8 +59,9 @@ void CompositorOperation::deinit_execution()
|
|||
|
||||
if (rr) {
|
||||
RenderView *rv = RE_RenderViewGetByName(rr, view_name_);
|
||||
ImBuf *ibuf = RE_RenderViewEnsureImBuf(rr, rv);
|
||||
|
||||
RE_RenderBuffer_assign_data(&rv->combined_buffer, output_buffer_);
|
||||
IMB_assign_float_buffer(ibuf, output_buffer_, IB_TAKE_OWNERSHIP);
|
||||
|
||||
rr->have_combined = true;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "eevee_private.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -582,7 +584,7 @@ static void eevee_cryptomatte_extract_render_passes(
|
|||
const int pass_offset = pass * 2;
|
||||
SNPRINTF_RLEN(cryptomatte_pass_name, render_pass_name_format, pass);
|
||||
RenderPass *rp_object = RE_pass_find_by_name(rl, cryptomatte_pass_name, viewname);
|
||||
float *rp_buffer_data = rp_object->buffer.data;
|
||||
float *rp_buffer_data = rp_object->ibuf->float_buffer.data;
|
||||
for (int y = 0; y < rect_height; y++) {
|
||||
for (int x = 0; x < rect_width; x++) {
|
||||
const int accum_buffer_offset = (rect_offset_x + x +
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "eevee_private.h"
|
||||
|
||||
bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, Depsgraph *depsgraph)
|
||||
|
@ -267,7 +269,7 @@ static void eevee_render_color_result(RenderLayer *rl,
|
|||
num_channels,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->buffer.data);
|
||||
rp->ibuf->float_buffer.data);
|
||||
}
|
||||
|
||||
static void eevee_render_result_combined(RenderLayer *rl,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "DNA_ID.h"
|
||||
#include "DNA_lightprobe_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "eevee_engine.h"
|
||||
|
@ -362,7 +363,9 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na
|
|||
RenderPass *vector_rp = RE_pass_find_by_name(
|
||||
render_layer, vector_pass_name.c_str(), view_name);
|
||||
if (vector_rp) {
|
||||
memset(vector_rp->buffer.data, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
|
||||
memset(vector_rp->ibuf->float_buffer.data,
|
||||
0,
|
||||
sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "gpencil_engine.h"
|
||||
|
||||
void GPENCIL_render_init(GPENCIL_Data *vedata,
|
||||
|
@ -50,8 +52,8 @@ void GPENCIL_render_init(GPENCIL_Data *vedata,
|
|||
RenderPass *rpass_z_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
|
||||
RenderPass *rpass_col_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
|
||||
|
||||
float *pix_z = (rpass_z_src) ? rpass_z_src->buffer.data : NULL;
|
||||
float *pix_col = (rpass_col_src) ? rpass_col_src->buffer.data : NULL;
|
||||
float *pix_z = (rpass_z_src) ? rpass_z_src->ibuf->float_buffer.data : NULL;
|
||||
float *pix_col = (rpass_col_src) ? rpass_col_src->ibuf->float_buffer.data : NULL;
|
||||
|
||||
if (!pix_z || !pix_col) {
|
||||
RE_engine_set_error_message(engine,
|
||||
|
@ -161,7 +163,7 @@ static void GPENCIL_render_result_z(RenderLayer *rl,
|
|||
|
||||
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
|
||||
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
|
||||
float *ro_buffer_data = rp->buffer.data;
|
||||
float *ro_buffer_data = rp->ibuf->float_buffer.data;
|
||||
|
||||
GPU_framebuffer_read_depth(vedata->fbl->render_fb,
|
||||
rect->xmin,
|
||||
|
@ -223,7 +225,7 @@ static void GPENCIL_render_result_combined(RenderLayer *rl,
|
|||
4,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->buffer.data);
|
||||
rp->ibuf->float_buffer.data);
|
||||
}
|
||||
|
||||
void GPENCIL_render_to_image(void *ved,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "ED_paint.h"
|
||||
#include "ED_view3d.h"
|
||||
#include "GPU_capabilities.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "draw_common.hh"
|
||||
#include "draw_sculpt.hh"
|
||||
|
@ -656,7 +657,7 @@ static void write_render_color_output(RenderLayer *layer,
|
|||
4,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->buffer.data);
|
||||
rp->ibuf->float_buffer.data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -675,13 +676,13 @@ static void write_render_z_output(RenderLayer *layer,
|
|||
BLI_rcti_size_x(rect),
|
||||
BLI_rcti_size_y(rect),
|
||||
GPU_DATA_FLOAT,
|
||||
rp->buffer.data);
|
||||
rp->ibuf->float_buffer.data);
|
||||
|
||||
int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
|
||||
|
||||
/* Convert GPU depth [0..1] to view Z [near..far] */
|
||||
if (DRW_view_is_persp_get(nullptr)) {
|
||||
for (float &z : MutableSpan(rp->buffer.data, pix_num)) {
|
||||
for (float &z : MutableSpan(rp->ibuf->float_buffer.data, pix_num)) {
|
||||
if (z == 1.0f) {
|
||||
z = 1e10f; /* Background */
|
||||
}
|
||||
|
@ -697,7 +698,7 @@ static void write_render_z_output(RenderLayer *layer,
|
|||
float far = DRW_view_far_distance_get(nullptr);
|
||||
float range = fabsf(far - near);
|
||||
|
||||
for (float &z : MutableSpan(rp->buffer.data, pix_num)) {
|
||||
for (float &z : MutableSpan(rp->ibuf->float_buffer.data, pix_num)) {
|
||||
if (z == 1.0f) {
|
||||
z = 1e10f; /* Background */
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "workbench_private.h"
|
||||
|
@ -104,7 +106,7 @@ static void workbench_render_result_z(RenderLayer *rl, const char *viewname, con
|
|||
|
||||
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
|
||||
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
|
||||
float *rp_buffer_data = rp->buffer.data;
|
||||
float *rp_buffer_data = rp->ibuf->float_buffer.data;
|
||||
|
||||
GPU_framebuffer_bind(dfbl->default_fb);
|
||||
GPU_framebuffer_read_depth(dfbl->default_fb,
|
||||
|
@ -208,7 +210,7 @@ void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer
|
|||
4,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->buffer.data);
|
||||
rp->ibuf->float_buffer.data);
|
||||
|
||||
workbench_render_result_z(render_layer, viewname, rect);
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ static bool eyedropper_cryptomatte_sample_renderlayer_fl(RenderLayer *render_lay
|
|||
const int y = int(fpos[1] * render_pass->recty);
|
||||
const int offset = 4 * (y * render_pass->rectx + x);
|
||||
zero_v3(r_col);
|
||||
r_col[0] = render_pass->buffer.data[offset];
|
||||
r_col[0] = render_pass->ibuf->float_buffer.data[offset];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,16 +204,19 @@ static void image_buffer_rect_update(RenderJob *rj,
|
|||
*/
|
||||
/* TODO(sergey): Need to check has_combined here? */
|
||||
if (iuser->pass == 0) {
|
||||
RenderView *rv;
|
||||
const int view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
|
||||
rv = RE_RenderViewGetById(rr, view_id);
|
||||
const RenderView *rv = RE_RenderViewGetById(rr, view_id);
|
||||
|
||||
if (rv->ibuf == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* find current float rect for display, first case is after composite... still weak */
|
||||
if (rv->combined_buffer.data) {
|
||||
rectf = rv->combined_buffer.data;
|
||||
if (rv->ibuf->float_buffer.data) {
|
||||
rectf = rv->ibuf->float_buffer.data;
|
||||
}
|
||||
else {
|
||||
if (rv->byte_buffer.data) {
|
||||
if (rv->ibuf->byte_buffer.data) {
|
||||
/* special case, currently only happens with sequencer rendering,
|
||||
* which updates the whole frame, so we can only mark display buffer
|
||||
* as invalid here (sergey)
|
||||
|
|
|
@ -194,8 +194,7 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
|
|||
RenderView *rv_del = rv->next;
|
||||
BLI_remlink(&rr->views, rv_del);
|
||||
|
||||
RE_RenderBuffer_data_free(&rv_del->combined_buffer);
|
||||
RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
|
||||
IMB_freeImBuf(rv_del->ibuf);
|
||||
|
||||
MEM_freeN(rv_del);
|
||||
}
|
||||
|
@ -219,8 +218,7 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
|
|||
|
||||
BLI_remlink(&rr->views, rv_del);
|
||||
|
||||
RE_RenderBuffer_data_free(&rv_del->combined_buffer);
|
||||
RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
|
||||
IMB_freeImBuf(rv_del->ibuf);
|
||||
|
||||
MEM_freeN(rv_del);
|
||||
}
|
||||
|
|
|
@ -668,7 +668,7 @@ static bool ed_preview_draw_rect(
|
|||
rv = nullptr;
|
||||
}
|
||||
|
||||
if (rv && rv->combined_buffer.data) {
|
||||
if (rv && rv->ibuf) {
|
||||
if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) {
|
||||
newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
|
||||
newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
|
||||
|
@ -677,13 +677,8 @@ static bool ed_preview_draw_rect(
|
|||
float fx = rect->xmin + offx;
|
||||
float fy = rect->ymin;
|
||||
|
||||
ImBuf *ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 0, 0);
|
||||
IMB_assign_float_buffer(ibuf, rv->combined_buffer.data, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
|
||||
ED_draw_imbuf(
|
||||
ibuf, fx, fy, false, &scene->view_settings, &scene->display_settings, 1.0f, 1.0f);
|
||||
|
||||
IMB_freeImBuf(ibuf);
|
||||
rv->ibuf, fx, fy, false, &scene->view_settings, &scene->display_settings, 1.0f, 1.0f);
|
||||
|
||||
ok = true;
|
||||
}
|
||||
|
@ -1062,9 +1057,11 @@ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Rend
|
|||
/* Create buffer in empty RenderView created in the init step. */
|
||||
RenderResult *rr = RE_AcquireResultWrite(re);
|
||||
RenderView *rv = (RenderView *)rr->views.first;
|
||||
RE_RenderBuffer_assign_data(&rv->combined_buffer,
|
||||
static_cast<float *>(MEM_callocN(sizeof(float[4]) * width * height,
|
||||
"texture render result")));
|
||||
ImBuf *rv_ibuf = RE_RenderViewEnsureImBuf(rr, rv);
|
||||
IMB_assign_float_buffer(rv_ibuf,
|
||||
static_cast<float *>(MEM_callocN(sizeof(float[4]) * width * height,
|
||||
"texture render result")),
|
||||
IB_TAKE_OWNERSHIP);
|
||||
RE_ReleaseResult(re);
|
||||
|
||||
/* Get texture image pool (if any) */
|
||||
|
@ -1072,7 +1069,7 @@ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Rend
|
|||
BKE_texture_fetch_images_for_pool(tex, img_pool);
|
||||
|
||||
/* Fill in image buffer. */
|
||||
float *rect_float = rv->combined_buffer.data;
|
||||
float *rect_float = rv_ibuf->float_buffer.data;
|
||||
float tex_coord[3] = {0.0f, 0.0f, 0.0f};
|
||||
bool color_manage = BKE_scene_check_color_management_enabled(sce);
|
||||
|
||||
|
|
|
@ -128,10 +128,14 @@ static bool ui_imageuser_slot_menu_step(bContext *C, int direction, void *image_
|
|||
static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
|
||||
{
|
||||
RenderView *rv = RE_RenderViewGetById(rr, 0);
|
||||
if (rv->combined_buffer.data) {
|
||||
ImBuf *ibuf = rv->ibuf;
|
||||
if (!ibuf) {
|
||||
return NULL;
|
||||
}
|
||||
if (ibuf->float_buffer.data) {
|
||||
return IFACE_("Composite");
|
||||
}
|
||||
if (rv->byte_buffer.data) {
|
||||
if (ibuf->byte_buffer.data) {
|
||||
return IFACE_("Sequence");
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -47,6 +47,8 @@ using namespace Freestyle;
|
|||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
|
||||
#include "pipeline.hh"
|
||||
|
||||
#include "FRS_freestyle.h"
|
||||
|
@ -447,7 +449,7 @@ static void prepare(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph)
|
|||
RenderLayer *rl = RE_GetRenderLayer(re->result, view_layer->name);
|
||||
bool diffuse = false, z = false;
|
||||
for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
|
||||
float *rpass_buffer_data = rpass->buffer.data;
|
||||
float *rpass_buffer_data = rpass->ibuf->float_buffer.data;
|
||||
if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE_COLOR)) {
|
||||
controller->setPassDiffuse(rpass_buffer_data, rpass->rectx, rpass->recty);
|
||||
diffuse = true;
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "../blenlib/BLI_sys_types.h"
|
||||
#include "../gpu/GPU_texture.h"
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
@ -152,19 +151,6 @@ struct ImBuf *IMB_allocFromBuffer(const uint8_t *byte_buffer,
|
|||
unsigned int h,
|
||||
unsigned int channels);
|
||||
|
||||
/**
|
||||
* Assign the content of the corresponding buffer using an implicitly shareable data pointer.
|
||||
*
|
||||
* \note Does not modify the topology (width, height, number of channels)
|
||||
* or the mipmaps in any way.
|
||||
*/
|
||||
void IMB_assign_shared_byte_buffer(struct ImBuf *ibuf,
|
||||
uint8_t *buffer_data,
|
||||
const ImplicitSharingInfoHandle *implicit_sharing);
|
||||
void IMB_assign_shared_float_buffer(struct ImBuf *ibuf,
|
||||
float *buffer_data,
|
||||
const ImplicitSharingInfoHandle *implicit_sharing);
|
||||
|
||||
/**
|
||||
* Assign the content of the corresponding buffer with the given data and ownership.
|
||||
* The current content of the buffer is released corresponding to its ownership configuration.
|
||||
|
@ -847,9 +833,13 @@ bool imb_addrectfloatImBuf(struct ImBuf *ibuf, const unsigned int channels);
|
|||
void imb_freerectfloatImBuf(struct ImBuf *ibuf);
|
||||
void imb_freemipmapImBuf(struct ImBuf *ibuf);
|
||||
|
||||
/** Free all pixel data (associated with image size). */
|
||||
/** Free all CPU pixel data (associated with image size). */
|
||||
void imb_freerectImbuf_all(struct ImBuf *ibuf);
|
||||
|
||||
/* Free the GPU textures of the given image buffer, leaving the CPU buffers unchanged.
|
||||
* The ibuf can be nullptr, in which case the function does nothing. */
|
||||
void IMB_free_gpu_textures(struct ImBuf *ibuf);
|
||||
|
||||
/**
|
||||
* Threaded processors.
|
||||
*/
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
|
||||
#include "DNA_vec_types.h" /* for rcti */
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
struct GPUTexture;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -172,17 +172,14 @@ typedef enum ImBufOwnership {
|
|||
|
||||
/* Different storage specialization.
|
||||
*
|
||||
* Note on the implicit sharing
|
||||
* ----------------------------
|
||||
* NOTE: Avoid direct assignments and allocations, use the buffer utilities from the IMB_imbuf.h
|
||||
* instead.
|
||||
*
|
||||
* The buffer allows implicitly sharing data with other users of such data. In this case the
|
||||
* ownership is set to IB_DO_NOT_TAKE_OWNERSHIP. */
|
||||
/* TODO(sergey): Once everything is C++ replace with a template. */
|
||||
* Accessing the data pointer directly is fine and is an expected way of accessing it. */
|
||||
|
||||
typedef struct ImBufByteBuffer {
|
||||
uint8_t *data;
|
||||
ImBufOwnership ownership;
|
||||
const ImplicitSharingInfoHandle *implicit_sharing;
|
||||
|
||||
struct ColorSpace *colorspace;
|
||||
} ImBufByteBuffer;
|
||||
|
@ -190,11 +187,20 @@ typedef struct ImBufByteBuffer {
|
|||
typedef struct ImBufFloatBuffer {
|
||||
float *data;
|
||||
ImBufOwnership ownership;
|
||||
const ImplicitSharingInfoHandle *implicit_sharing;
|
||||
|
||||
struct ColorSpace *colorspace;
|
||||
} ImBufFloatBuffer;
|
||||
|
||||
typedef struct ImBufGPU {
|
||||
/* Texture which corresponds to the state of the ImBug on the GPU.
|
||||
*
|
||||
* Allocation is supposed to happen outside of the ImBug module from a proper GPU context.
|
||||
* De-referencing the ImBuf or its GPU texture can happen from any state. */
|
||||
/* TODO(sergey): This should become a list of textures, to support having high-res ImBuf on GPU
|
||||
* without hitting hardware limitations. */
|
||||
struct GPUTexture *texture;
|
||||
} ImBufGPU;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -236,6 +242,9 @@ typedef struct ImBuf {
|
|||
*/
|
||||
ImBufFloatBuffer float_buffer;
|
||||
|
||||
/* Image buffer on the GPU. */
|
||||
ImBufGPU gpu;
|
||||
|
||||
/** Resolution in pixels per meter. Multiply by `0.0254` for DPI. */
|
||||
double ppm[2];
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_implicit_sharing.hh"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "GPU_texture.h"
|
||||
|
||||
static SpinLock refcounter_spin;
|
||||
|
||||
void imb_refcounter_lock_init()
|
||||
|
@ -67,16 +68,12 @@ void imb_mmap_unlock()
|
|||
* buffer to its defaults. */
|
||||
template<class BufferType> static void imb_free_buffer(BufferType &buffer)
|
||||
{
|
||||
if (buffer.implicit_sharing) {
|
||||
blender::implicit_sharing::free_shared_data(&buffer.data, &buffer.implicit_sharing);
|
||||
}
|
||||
else if (buffer.data) {
|
||||
if (buffer.data) {
|
||||
switch (buffer.ownership) {
|
||||
case IB_DO_NOT_TAKE_OWNERSHIP:
|
||||
break;
|
||||
|
||||
case IB_TAKE_OWNERSHIP:
|
||||
BLI_assert(buffer.implicit_sharing == nullptr);
|
||||
MEM_freeN(buffer.data);
|
||||
break;
|
||||
}
|
||||
|
@ -85,7 +82,6 @@ template<class BufferType> static void imb_free_buffer(BufferType &buffer)
|
|||
/* Reset buffer to defaults. */
|
||||
buffer.data = nullptr;
|
||||
buffer.ownership = IB_DO_NOT_TAKE_OWNERSHIP;
|
||||
buffer.implicit_sharing = nullptr;
|
||||
}
|
||||
|
||||
/* Allocate pixel storage of the given buffer. The buffer owns the allocated memory.
|
||||
|
@ -101,7 +97,6 @@ bool imb_alloc_buffer(
|
|||
}
|
||||
|
||||
buffer.ownership = IB_TAKE_OWNERSHIP;
|
||||
buffer.implicit_sharing = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -119,12 +114,6 @@ template<class BufferType> void imb_make_writeable_buffer(BufferType &buffer)
|
|||
buffer.data = static_cast<decltype(BufferType::data)>(MEM_dupallocN(buffer.data));
|
||||
buffer.ownership = IB_TAKE_OWNERSHIP;
|
||||
|
||||
if (buffer.implicit_sharing) {
|
||||
buffer.implicit_sharing->remove_user_and_delete_if_last();
|
||||
buffer.implicit_sharing = nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
case IB_TAKE_OWNERSHIP:
|
||||
break;
|
||||
}
|
||||
|
@ -157,30 +146,6 @@ auto imb_steal_buffer_data(BufferType &buffer) -> decltype(BufferType::data)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/* Assign the new data of the buffer which is implicitly shared via the given handle.
|
||||
* The old content of the buffer is freed using imb_free_buffer. */
|
||||
template<class BufferType>
|
||||
void imb_assign_shared_buffer(BufferType &buffer,
|
||||
decltype(BufferType::data) buffer_data,
|
||||
const ImplicitSharingInfoHandle *implicit_sharing)
|
||||
{
|
||||
imb_free_buffer(buffer);
|
||||
|
||||
if (implicit_sharing) {
|
||||
BLI_assert(buffer_data != nullptr);
|
||||
|
||||
blender::implicit_sharing::copy_shared_pointer(
|
||||
buffer_data, implicit_sharing, &buffer.data, &buffer.implicit_sharing);
|
||||
}
|
||||
else {
|
||||
BLI_assert(buffer_data == nullptr);
|
||||
buffer.data = nullptr;
|
||||
buffer.implicit_sharing = nullptr;
|
||||
}
|
||||
|
||||
buffer.ownership = IB_DO_NOT_TAKE_OWNERSHIP;
|
||||
}
|
||||
|
||||
void imb_freemipmapImBuf(ImBuf *ibuf)
|
||||
{
|
||||
int a;
|
||||
|
@ -244,6 +209,16 @@ void imb_freerectImbuf_all(ImBuf *ibuf)
|
|||
freeencodedbufferImBuf(ibuf);
|
||||
}
|
||||
|
||||
void IMB_free_gpu_textures(ImBuf *ibuf)
|
||||
{
|
||||
if (!ibuf || !ibuf->gpu.texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_texture_free(ibuf->gpu.texture);
|
||||
ibuf->gpu.texture = nullptr;
|
||||
}
|
||||
|
||||
void IMB_freeImBuf(ImBuf *ibuf)
|
||||
{
|
||||
if (ibuf == nullptr) {
|
||||
|
@ -267,6 +242,7 @@ void IMB_freeImBuf(ImBuf *ibuf)
|
|||
"'.blend' relative \"//\" must not be used in ImBuf!");
|
||||
|
||||
imb_freerectImbuf_all(ibuf);
|
||||
IMB_free_gpu_textures(ibuf);
|
||||
IMB_metadata_free(ibuf->metadata);
|
||||
colormanage_cache_free(ibuf);
|
||||
|
||||
|
@ -459,32 +435,6 @@ void IMB_make_writable_float_buffer(ImBuf *ibuf)
|
|||
imb_make_writeable_buffer(ibuf->float_buffer);
|
||||
}
|
||||
|
||||
void IMB_assign_shared_byte_buffer(ImBuf *ibuf,
|
||||
uint8_t *buffer_data,
|
||||
const ImplicitSharingInfoHandle *implicit_sharing)
|
||||
{
|
||||
imb_free_buffer(ibuf->byte_buffer);
|
||||
ibuf->flags &= ~IB_rect;
|
||||
|
||||
if (buffer_data) {
|
||||
imb_assign_shared_buffer(ibuf->byte_buffer, buffer_data, implicit_sharing);
|
||||
ibuf->flags |= IB_rect;
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_assign_shared_float_buffer(ImBuf *ibuf,
|
||||
float *buffer_data,
|
||||
const ImplicitSharingInfoHandle *implicit_sharing)
|
||||
{
|
||||
imb_free_buffer(ibuf->float_buffer);
|
||||
ibuf->flags &= ~IB_rectfloat;
|
||||
|
||||
if (buffer_data) {
|
||||
imb_assign_shared_buffer(ibuf->float_buffer, buffer_data, implicit_sharing);
|
||||
ibuf->flags |= IB_rectfloat;
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, const ImBufOwnership ownership)
|
||||
{
|
||||
imb_free_buffer(ibuf->byte_buffer);
|
||||
|
@ -626,8 +576,6 @@ ImBuf *IMB_dupImBuf(const ImBuf *ibuf1)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/* TODO(sergey): Use implicit sharing. */
|
||||
|
||||
if (ibuf1->byte_buffer.data) {
|
||||
flags |= IB_rect;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ const EnumPropertyItem rna_enum_bake_pass_type_items[] = {
|
|||
# include "GPU_capabilities.h"
|
||||
# include "GPU_shader.h"
|
||||
# include "IMB_colormanagement.h"
|
||||
# include "IMB_imbuf_types.h"
|
||||
|
||||
# include "DEG_depsgraph_query.h"
|
||||
|
||||
|
@ -499,15 +500,30 @@ static int rna_RenderPass_rect_get_length(const PointerRNA *ptr,
|
|||
static void rna_RenderPass_rect_get(PointerRNA *ptr, float *values)
|
||||
{
|
||||
RenderPass *rpass = (RenderPass *)ptr->data;
|
||||
memcpy(
|
||||
values, rpass->buffer.data, sizeof(float) * rpass->rectx * rpass->recty * rpass->channels);
|
||||
const size_t size_in_bytes = sizeof(float) * rpass->rectx * rpass->recty * rpass->channels;
|
||||
const float *buffer = rpass->ibuf ? rpass->ibuf->float_buffer.data : nullptr;
|
||||
|
||||
if (!buffer) {
|
||||
/* No float buffer to read from, initialize to all zeroes. */
|
||||
memset(values, 0, size_in_bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(values, buffer, size_in_bytes);
|
||||
}
|
||||
|
||||
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values)
|
||||
{
|
||||
RenderPass *rpass = (RenderPass *)ptr->data;
|
||||
memcpy(
|
||||
rpass->buffer.data, values, sizeof(float) * rpass->rectx * rpass->recty * rpass->channels);
|
||||
float *buffer = rpass->ibuf ? rpass->ibuf->float_buffer.data : nullptr;
|
||||
|
||||
if (!buffer) {
|
||||
/* Only writing to an already existing buffer is supported. */
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t size_in_bytes = sizeof(float) * rpass->rectx * rpass->recty * rpass->channels;
|
||||
memcpy(buffer, values, size_in_bytes);
|
||||
}
|
||||
|
||||
static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, const char *view)
|
||||
|
|
|
@ -42,43 +42,14 @@ extern "C" {
|
|||
/* only used as handle */
|
||||
typedef struct Render Render;
|
||||
|
||||
/* Buffer of a floating point values which uses implicit sharing.
|
||||
*
|
||||
* The buffer is allocated by render passes creation, and then is shared with the render result
|
||||
* and image buffer.
|
||||
*
|
||||
* The GPU texture is an optional read-only copy of the render buffer in GPU memory. */
|
||||
typedef struct RenderBuffer {
|
||||
float *data;
|
||||
const ImplicitSharingInfoHandle *sharing_info;
|
||||
struct GPUTexture *gpu_texture;
|
||||
} RenderBuffer;
|
||||
|
||||
/* Specialized render buffer to store 8bpp passes. */
|
||||
typedef struct RenderByteBuffer {
|
||||
uint8_t *data;
|
||||
const ImplicitSharingInfoHandle *sharing_info;
|
||||
struct GPUTexture *gpu_texture;
|
||||
} RenderByteBuffer;
|
||||
|
||||
/* Render Result usage:
|
||||
*
|
||||
* - render engine allocates/frees and delivers raw floating point rects
|
||||
* - right now it's full rects, but might become tiles or file
|
||||
* - the display client has to allocate display rects, sort out what to display,
|
||||
* and how it's converted
|
||||
*/
|
||||
|
||||
typedef struct RenderView {
|
||||
struct RenderView *next, *prev;
|
||||
char name[64]; /* EXR_VIEW_MAXNAME */
|
||||
|
||||
/* if this exists, result of composited layers */
|
||||
RenderBuffer combined_buffer;
|
||||
|
||||
/* optional, 32 bits version of picture, used for sequencer, OpenGL render and image curves */
|
||||
RenderByteBuffer byte_buffer;
|
||||
|
||||
/* Image buffer of a composited layer or a sequencer output.
|
||||
* The ibuf is only allocated if it has an actual data in one of its buffers (float, byte, or
|
||||
* GPU). */
|
||||
struct ImBuf *ibuf;
|
||||
} RenderView;
|
||||
|
||||
typedef struct RenderPass {
|
||||
|
@ -87,7 +58,14 @@ typedef struct RenderPass {
|
|||
char name[64]; /* amount defined in IMB_openexr.h */
|
||||
char chan_id[8]; /* amount defined in IMB_openexr.h */
|
||||
|
||||
RenderBuffer buffer;
|
||||
/* Image buffer which contains data of this pass.
|
||||
*
|
||||
* The data can be either CPU side stored in ibuf->float_buffer, or a GPU-side stored in
|
||||
* ibuf->gpu (during rendering, i.e.).
|
||||
*
|
||||
* The pass data storage is lazily allocated, and until data is actually provided (via either CPU
|
||||
* buffer of GPU texture) the ibuf is not allocated. */
|
||||
struct ImBuf *ibuf;
|
||||
|
||||
int rectx, recty;
|
||||
|
||||
|
@ -126,14 +104,10 @@ typedef struct RenderResult {
|
|||
/* target image size */
|
||||
int rectx, recty;
|
||||
|
||||
/* The following byte, combined, and z buffers are for temporary storage only,
|
||||
* for RenderResult structs created in #RE_AcquireResultImage - which do not have RenderView */
|
||||
|
||||
/* Optional, 32 bits version of picture, used for OpenGL render and image curves. */
|
||||
RenderByteBuffer byte_buffer;
|
||||
|
||||
/* if this exists, a copy of one of layers, or result of composited layers */
|
||||
RenderBuffer combined_buffer;
|
||||
/* The temporary storage to pass image data from #RE_AcquireResultImage.
|
||||
* Is null pointer when the RenderResult is not coming from the #RE_AcquireResultImage, and is
|
||||
* a pointer to an existing ibuf in either RenderView or a RenderPass otherwise. */
|
||||
struct ImBuf *ibuf;
|
||||
|
||||
/* coordinates within final image (after cropping) */
|
||||
rcti tilerect;
|
||||
|
@ -285,9 +259,9 @@ void RE_render_result_rect_from_ibuf(struct RenderResult *rr,
|
|||
|
||||
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
|
||||
float *RE_RenderLayerGetPass(struct RenderLayer *rl, const char *name, const char *viewname);
|
||||
RenderBuffer *RE_RenderLayerGetPassBuffer(struct RenderLayer *rl,
|
||||
const char *name,
|
||||
const char *viewname);
|
||||
struct ImBuf *RE_RenderLayerGetPassImBuf(struct RenderLayer *rl,
|
||||
const char *name,
|
||||
const char *viewname);
|
||||
|
||||
bool RE_HasSingleLayer(struct Render *re);
|
||||
|
||||
|
@ -510,42 +484,8 @@ struct RenderView *RE_RenderViewGetByName(struct RenderResult *rr, const char *v
|
|||
|
||||
RenderResult *RE_DuplicateRenderResult(RenderResult *rr);
|
||||
|
||||
/**
|
||||
* Create new render buffer which takes ownership of the given data.
|
||||
* Creates an implicit sharing handle for the data as well. */
|
||||
RenderBuffer RE_RenderBuffer_new(float *data);
|
||||
|
||||
/**
|
||||
* Assign the buffer data.
|
||||
*
|
||||
* The current buffer data is freed and the new one is assigned, and the implicit sharing for it.
|
||||
*/
|
||||
void RE_RenderBuffer_assign_data(RenderBuffer *render_buffer, float *data);
|
||||
|
||||
/**
|
||||
* Effectively `lhs = rhs`. The lhs will share the same buffer as the rhs (with an increased user
|
||||
* counter).
|
||||
*
|
||||
* The current content of the lhs is freed.
|
||||
* The rhs and its data is allowed to be nullptr, in which case the lhs's data will be nullptr
|
||||
* after this call.
|
||||
*/
|
||||
void RE_RenderBuffer_assign_shared(RenderBuffer *lhs, const RenderBuffer *rhs);
|
||||
|
||||
/**
|
||||
* Free data of the given buffer.
|
||||
*
|
||||
* The data and implicit sharing information of the buffer is set to nullptr after this call.
|
||||
* The buffer itself is not freed.
|
||||
*/
|
||||
void RE_RenderBuffer_data_free(RenderBuffer *render_buffer);
|
||||
|
||||
/* Implementation of above, but for byte buffer. */
|
||||
/* TODO(sergey): Once everything is C++ we can remove the duplicated API. */
|
||||
RenderByteBuffer RE_RenderByteBuffer_new(uint8_t *data);
|
||||
void RE_RenderByteBuffer_assign_data(RenderByteBuffer *render_buffer, uint8_t *data);
|
||||
void RE_RenderByteBuffer_assign_shared(RenderByteBuffer *lhs, const RenderByteBuffer *rhs);
|
||||
void RE_RenderByteBuffer_data_free(RenderByteBuffer *render_buffer);
|
||||
struct ImBuf *RE_RenderPassEnsureImBuf(RenderPass *render_pass);
|
||||
struct ImBuf *RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *render_view);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ class Context : public realtime_compositor::Context {
|
|||
RenderPass *rpass = (RenderPass *)BLI_findstring(
|
||||
&rl->passes, pass_name, offsetof(RenderPass, name));
|
||||
|
||||
if (rpass && rpass->buffer.data) {
|
||||
if (rpass && rpass->ibuf && rpass->ibuf->float_buffer.data) {
|
||||
input_texture = RE_pass_ensure_gpu_texture_cache(re, rpass);
|
||||
|
||||
if (input_texture) {
|
||||
|
@ -283,7 +283,8 @@ class Context : public realtime_compositor::Context {
|
|||
float *output_buffer = (float *)GPU_texture_read(output_texture_, GPU_DATA_FLOAT, 0);
|
||||
|
||||
if (output_buffer) {
|
||||
RE_RenderBuffer_assign_data(&rv->combined_buffer, output_buffer);
|
||||
ImBuf *ibuf = RE_RenderViewEnsureImBuf(rr, rv);
|
||||
IMB_assign_float_buffer(ibuf, output_buffer, IB_TAKE_OWNERSHIP);
|
||||
}
|
||||
|
||||
/* TODO: z-buffer output. */
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
# include "BPY_extern.h"
|
||||
#endif
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "RE_bake.h"
|
||||
#include "RE_engine.h"
|
||||
#include "RE_pipeline.h"
|
||||
|
@ -216,8 +218,8 @@ static RenderResult *render_result_from_bake(
|
|||
/* 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;
|
||||
float *primitive = primitive_pass->buffer.data + offset;
|
||||
float *differential = differential_pass->buffer.data + offset;
|
||||
float *primitive = primitive_pass->ibuf->float_buffer.data + offset;
|
||||
float *differential = differential_pass->ibuf->float_buffer.data + offset;
|
||||
|
||||
size_t bake_offset = (y + ty) * image->width + x;
|
||||
const BakePixel *bake_pixel = pixels + bake_offset;
|
||||
|
@ -284,7 +286,7 @@ static void render_result_to_bake(RenderEngine *engine, RenderResult *rr)
|
|||
const size_t offset = ty * w;
|
||||
const size_t bake_offset = (y + ty) * image->width + x;
|
||||
|
||||
const float *pass_rect = rpass->buffer.data + offset * channels_num;
|
||||
const float *pass_rect = rpass->ibuf->float_buffer.data + offset * channels_num;
|
||||
const BakePixel *bake_pixel = pixels + bake_offset;
|
||||
float *bake_result = result + bake_offset * channels_num;
|
||||
|
||||
|
|
|
@ -228,16 +228,16 @@ void RE_FreeRenderResult(RenderResult *rr)
|
|||
render_result_free(rr);
|
||||
}
|
||||
|
||||
RenderBuffer *RE_RenderLayerGetPassBuffer(RenderLayer *rl, const char *name, const char *viewname)
|
||||
ImBuf *RE_RenderLayerGetPassImBuf(RenderLayer *rl, const char *name, const char *viewname)
|
||||
{
|
||||
RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname);
|
||||
return rpass ? &rpass->buffer : nullptr;
|
||||
return rpass ? rpass->ibuf : nullptr;
|
||||
}
|
||||
|
||||
float *RE_RenderLayerGetPass(RenderLayer *rl, const char *name, const char *viewname)
|
||||
{
|
||||
RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname);
|
||||
return rpass ? rpass->buffer.data : nullptr;
|
||||
const ImBuf *ibuf = RE_RenderLayerGetPassImBuf(rl, name, viewname);
|
||||
return ibuf ? ibuf->float_buffer.data : nullptr;
|
||||
}
|
||||
|
||||
RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
|
||||
|
@ -381,7 +381,7 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
|
|||
render_result_views_shallowcopy(rr, re->result);
|
||||
|
||||
RenderView *rv = static_cast<RenderView *>(rr->views.first);
|
||||
rr->have_combined = (rv->combined_buffer.data != nullptr);
|
||||
rr->have_combined = (rv->ibuf != nullptr);
|
||||
|
||||
/* single layer */
|
||||
RenderLayer *rl = render_get_single_layer(re, re->result);
|
||||
|
@ -390,13 +390,9 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
|
|||
* explicitly free it. So simply assign the buffers as a shallow copy here as well. */
|
||||
|
||||
if (rl) {
|
||||
if (rv->combined_buffer.data == nullptr) {
|
||||
if (rv->ibuf == nullptr) {
|
||||
LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
|
||||
RenderBuffer *buffer = RE_RenderLayerGetPassBuffer(
|
||||
rl, RE_PASSNAME_COMBINED, rview->name);
|
||||
if (buffer) {
|
||||
rview->combined_buffer = *buffer;
|
||||
}
|
||||
rview->ibuf = RE_RenderLayerGetPassImBuf(rl, RE_PASSNAME_COMBINED, rview->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -435,24 +431,20 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
|
|||
|
||||
/* `scene.rd.actview` view. */
|
||||
rv = RE_RenderViewGetById(re->result, view_id);
|
||||
rr->have_combined = (rv->combined_buffer.data != nullptr);
|
||||
rr->have_combined = (rv->ibuf != nullptr);
|
||||
|
||||
/* The render result uses shallow initialization, and the caller is not expected to
|
||||
* explicitly free it. So simply assign the buffers as a shallow copy here as well.
|
||||
*
|
||||
* The thread safety is ensured via the re->resultmutex. */
|
||||
rr->combined_buffer = rv->combined_buffer;
|
||||
rr->byte_buffer = rv->byte_buffer;
|
||||
rr->ibuf = rv->ibuf;
|
||||
|
||||
/* active layer */
|
||||
rl = render_get_single_layer(re, re->result);
|
||||
|
||||
if (rl) {
|
||||
if (rv->combined_buffer.data == nullptr) {
|
||||
RenderBuffer *buffer = RE_RenderLayerGetPassBuffer(rl, RE_PASSNAME_COMBINED, rv->name);
|
||||
if (buffer) {
|
||||
rr->combined_buffer = *buffer;
|
||||
}
|
||||
if (rv->ibuf == nullptr) {
|
||||
rr->ibuf = RE_RenderLayerGetPassImBuf(rl, RE_PASSNAME_COMBINED, rv->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1311,8 +1303,8 @@ static void renderresult_stampinfo(Render *re)
|
|||
BKE_image_stamp_buf(re->scene,
|
||||
ob_camera_eval,
|
||||
(re->r.stamp & R_STAMP_STRIPMETA) ? rres.stamp_data : nullptr,
|
||||
rres.byte_buffer.data,
|
||||
rres.combined_buffer.data,
|
||||
rres.ibuf->byte_buffer.data,
|
||||
rres.ibuf->float_buffer.data,
|
||||
rres.rectx,
|
||||
rres.recty,
|
||||
4);
|
||||
|
@ -2594,7 +2586,7 @@ void RE_layer_load_from_file(
|
|||
IMB_float_from_rect(ibuf);
|
||||
}
|
||||
|
||||
memcpy(rpass->buffer.data,
|
||||
memcpy(rpass->ibuf->float_buffer.data,
|
||||
ibuf->float_buffer.data,
|
||||
sizeof(float[4]) * layer->rectx * layer->recty);
|
||||
}
|
||||
|
@ -2610,7 +2602,7 @@ void RE_layer_load_from_file(
|
|||
if (ibuf_clip) {
|
||||
IMB_rectcpy(ibuf_clip, ibuf, 0, 0, x, y, layer->rectx, layer->recty);
|
||||
|
||||
memcpy(rpass->buffer.data,
|
||||
memcpy(rpass->ibuf->float_buffer.data,
|
||||
ibuf_clip->float_buffer.data,
|
||||
sizeof(float[4]) * layer->rectx * layer->recty);
|
||||
IMB_freeImBuf(ibuf_clip);
|
||||
|
@ -2737,9 +2729,7 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha
|
|||
/* Clear previous pass if exist or the new image will be over previous one. */
|
||||
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
|
||||
if (rp) {
|
||||
rp->buffer.sharing_info->remove_user_and_delete_if_last();
|
||||
rp->buffer.sharing_info = nullptr;
|
||||
|
||||
IMB_freeImBuf(rp->ibuf);
|
||||
BLI_freelinkN(&rl->passes, rp);
|
||||
}
|
||||
/* create a totally new pass */
|
||||
|
|
|
@ -54,8 +54,7 @@ static void render_result_views_free(RenderResult *rr)
|
|||
RenderView *rv = static_cast<RenderView *>(rr->views.first);
|
||||
BLI_remlink(&rr->views, rv);
|
||||
|
||||
RE_RenderByteBuffer_data_free(&rv->byte_buffer);
|
||||
RE_RenderBuffer_data_free(&rv->combined_buffer);
|
||||
IMB_freeImBuf(rv->ibuf);
|
||||
|
||||
MEM_freeN(rv);
|
||||
}
|
||||
|
@ -75,7 +74,7 @@ void render_result_free(RenderResult *rr)
|
|||
while (rl->passes.first) {
|
||||
RenderPass *rpass = static_cast<RenderPass *>(rl->passes.first);
|
||||
|
||||
RE_RenderBuffer_data_free(&rpass->buffer);
|
||||
IMB_freeImBuf(rpass->ibuf);
|
||||
|
||||
BLI_freelinkN(&rl->passes, rpass);
|
||||
}
|
||||
|
@ -85,8 +84,7 @@ void render_result_free(RenderResult *rr)
|
|||
|
||||
render_result_views_free(rr);
|
||||
|
||||
RE_RenderByteBuffer_data_free(&rr->byte_buffer);
|
||||
RE_RenderBuffer_data_free(&rr->combined_buffer);
|
||||
IMB_freeImBuf(rr->ibuf);
|
||||
|
||||
if (rr->text) {
|
||||
MEM_freeN(rr->text);
|
||||
|
@ -119,10 +117,7 @@ void render_result_free_gpu_texture_caches(RenderResult *rr)
|
|||
{
|
||||
LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
|
||||
LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
|
||||
if (rpass->buffer.gpu_texture) {
|
||||
GPU_texture_free(rpass->buffer.gpu_texture);
|
||||
rpass->buffer.gpu_texture = nullptr;
|
||||
}
|
||||
IMB_free_gpu_textures(rpass->ibuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,8 +138,7 @@ void render_result_views_shallowcopy(RenderResult *dst, RenderResult *src)
|
|||
|
||||
STRNCPY(rv->name, rview->name);
|
||||
|
||||
rv->combined_buffer = rview->combined_buffer;
|
||||
rv->byte_buffer = rview->byte_buffer;
|
||||
rv->ibuf = rview->ibuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,14 +159,19 @@ void render_result_views_shallowdelete(RenderResult *rr)
|
|||
|
||||
static void render_layer_allocate_pass(RenderResult *rr, RenderPass *rp)
|
||||
{
|
||||
if (rp->buffer.data != nullptr) {
|
||||
if (rp->ibuf && rp->ibuf->float_buffer.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: In-lined manual allocation to support floating point buffers of an arbitrary number of
|
||||
* channels. */
|
||||
|
||||
const size_t rectsize = size_t(rr->rectx) * rr->recty * rp->channels;
|
||||
float *buffer_data = MEM_cnew_array<float>(rectsize, rp->name);
|
||||
|
||||
rp->buffer = RE_RenderBuffer_new(buffer_data);
|
||||
rp->ibuf = IMB_allocImBuf(rr->rectx, rr->recty, 32, 0);
|
||||
rp->ibuf->channels = rp->channels;
|
||||
IMB_assign_float_buffer(rp->ibuf, buffer_data, IB_TAKE_OWNERSHIP);
|
||||
|
||||
if (STREQ(rp->name, RE_PASSNAME_VECTOR)) {
|
||||
/* initialize to max speed */
|
||||
|
@ -415,15 +414,27 @@ void RE_create_render_pass(RenderResult *rr,
|
|||
|
||||
void RE_pass_set_buffer_data(RenderPass *pass, float *data)
|
||||
{
|
||||
RE_RenderBuffer_assign_data(&pass->buffer, data);
|
||||
ImBuf *ibuf = RE_RenderPassEnsureImBuf(pass);
|
||||
|
||||
IMB_assign_float_buffer(ibuf, data, IB_TAKE_OWNERSHIP);
|
||||
}
|
||||
|
||||
GPUTexture *RE_pass_ensure_gpu_texture_cache(Render *re, RenderPass *rpass)
|
||||
{
|
||||
if (rpass->buffer.gpu_texture) {
|
||||
return rpass->buffer.gpu_texture;
|
||||
ImBuf *ibuf = rpass->ibuf;
|
||||
|
||||
if (!ibuf) {
|
||||
/* No existing GPU texture, but also no CPU side data to create it from. */
|
||||
return nullptr;
|
||||
}
|
||||
if (rpass->buffer.data == nullptr) {
|
||||
|
||||
if (ibuf->gpu.texture) {
|
||||
/* Return existing GPU texture, regardless whether it also exists on CPU or not. */
|
||||
return ibuf->gpu.texture;
|
||||
}
|
||||
|
||||
if (ibuf->float_buffer.data == nullptr) {
|
||||
/* No CPU side data to create the texture from. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -431,20 +442,21 @@ GPUTexture *RE_pass_ensure_gpu_texture_cache(Render *re, RenderPass *rpass)
|
|||
(rpass->channels == 3) ? GPU_RGB16F :
|
||||
GPU_RGBA16F;
|
||||
|
||||
rpass->buffer.gpu_texture = GPU_texture_create_2d("RenderBuffer.gpu_texture",
|
||||
rpass->rectx,
|
||||
rpass->recty,
|
||||
1,
|
||||
format,
|
||||
GPU_TEXTURE_USAGE_GENERAL,
|
||||
nullptr);
|
||||
/* TODO(sergey): Use utility to assign the texture. */
|
||||
ibuf->gpu.texture = GPU_texture_create_2d("RenderBuffer.gpu_texture",
|
||||
rpass->rectx,
|
||||
rpass->recty,
|
||||
1,
|
||||
format,
|
||||
GPU_TEXTURE_USAGE_GENERAL,
|
||||
nullptr);
|
||||
|
||||
if (rpass->buffer.gpu_texture) {
|
||||
GPU_texture_update(rpass->buffer.gpu_texture, GPU_DATA_FLOAT, rpass->buffer.data);
|
||||
if (ibuf->gpu.texture) {
|
||||
GPU_texture_update(ibuf->gpu.texture, GPU_DATA_FLOAT, ibuf->float_buffer.data);
|
||||
re->result_has_gpu_texture_caches = true;
|
||||
}
|
||||
|
||||
return rpass->buffer.gpu_texture;
|
||||
return ibuf->gpu.texture;
|
||||
}
|
||||
|
||||
void RE_render_result_full_channel_name(char *fullname,
|
||||
|
@ -543,6 +555,8 @@ static void ml_addpass_cb(void *base,
|
|||
RenderPass *rpass = MEM_cnew<RenderPass>("loaded pass");
|
||||
|
||||
BLI_addtail(&rl->passes, rpass);
|
||||
rpass->rectx = rr->rectx;
|
||||
rpass->recty = rr->recty;
|
||||
rpass->channels = totchan;
|
||||
rl->passflag |= passtype_from_name(name);
|
||||
|
||||
|
@ -673,7 +687,7 @@ RenderResult *render_result_new_from_exr(
|
|||
rpass->recty = recty;
|
||||
|
||||
if (rpass->channels >= 3) {
|
||||
IMB_colormanagement_transform(rpass->buffer.data,
|
||||
IMB_colormanagement_transform(rpass->ibuf->float_buffer.data,
|
||||
rpass->rectx,
|
||||
rpass->recty,
|
||||
rpass->channels,
|
||||
|
@ -753,7 +767,11 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
|
|||
rpass = rpass->next)
|
||||
{
|
||||
/* For save buffers, skip any passes that are only saved to disk. */
|
||||
if (rpass->buffer.data == nullptr || rpassp->buffer.data == nullptr) {
|
||||
if (rpass->ibuf == nullptr || rpassp->ibuf == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (rpass->ibuf->float_buffer.data == nullptr ||
|
||||
rpassp->ibuf->float_buffer.data == nullptr) {
|
||||
continue;
|
||||
}
|
||||
/* Render-result have all passes, render-part only the active view's passes. */
|
||||
|
@ -761,7 +779,11 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
|
|||
continue;
|
||||
}
|
||||
|
||||
do_merge_tile(rr, rrpart, rpass->buffer.data, rpassp->buffer.data, rpass->channels);
|
||||
do_merge_tile(rr,
|
||||
rrpart,
|
||||
rpass->ibuf->float_buffer.data,
|
||||
rpassp->ibuf->float_buffer.data,
|
||||
rpass->channels);
|
||||
|
||||
/* manually get next render pass */
|
||||
rpassp = rpassp->next;
|
||||
|
@ -865,13 +887,23 @@ bool render_result_exr_file_read_path(RenderResult *rr,
|
|||
RE_render_result_full_channel_name(
|
||||
fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, a);
|
||||
|
||||
if (IMB_exr_set_channel(
|
||||
exrhandle, rl->name, fullname, xstride, ystride, rpass->buffer.data + a)) {
|
||||
if (IMB_exr_set_channel(exrhandle,
|
||||
rl->name,
|
||||
fullname,
|
||||
xstride,
|
||||
ystride,
|
||||
rpass->ibuf->float_buffer.data + a))
|
||||
{
|
||||
found_channels = true;
|
||||
}
|
||||
else if (rl_single) {
|
||||
if (IMB_exr_set_channel(
|
||||
exrhandle, nullptr, fullname, xstride, ystride, rpass->buffer.data + a)) {
|
||||
if (IMB_exr_set_channel(exrhandle,
|
||||
nullptr,
|
||||
fullname,
|
||||
xstride,
|
||||
ystride,
|
||||
rpass->ibuf->float_buffer.data + a))
|
||||
{
|
||||
found_channels = true;
|
||||
}
|
||||
else {
|
||||
|
@ -998,8 +1030,10 @@ ImBuf *RE_render_result_rect_to_ibuf(RenderResult *rr,
|
|||
RenderView *rv = RE_RenderViewGetById(rr, view_id);
|
||||
|
||||
/* if not exists, BKE_imbuf_write makes one */
|
||||
IMB_assign_shared_byte_buffer(ibuf, rv->byte_buffer.data, rv->byte_buffer.sharing_info);
|
||||
IMB_assign_shared_float_buffer(ibuf, rv->combined_buffer.data, rv->combined_buffer.sharing_info);
|
||||
if (rv->ibuf) {
|
||||
IMB_assign_byte_buffer(ibuf, rv->ibuf->byte_buffer.data, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
IMB_assign_float_buffer(ibuf, rv->ibuf->float_buffer.data, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
}
|
||||
|
||||
/* float factor for random dither, imbuf takes care of it */
|
||||
ibuf->dither = dither;
|
||||
|
@ -1041,34 +1075,36 @@ void RE_render_result_rect_from_ibuf(RenderResult *rr, const ImBuf *ibuf, const
|
|||
{
|
||||
RenderView *rv = RE_RenderViewGetById(rr, view_id);
|
||||
|
||||
ImBuf *rv_ibuf = RE_RenderViewEnsureImBuf(rr, rv);
|
||||
|
||||
if (ibuf->float_buffer.data) {
|
||||
rr->have_combined = true;
|
||||
|
||||
if (!rv->combined_buffer.data) {
|
||||
if (!rv_ibuf->float_buffer.data) {
|
||||
float *data = MEM_cnew_array<float>(4 * rr->rectx * rr->recty, "render_seq rectf");
|
||||
RE_RenderBuffer_assign_data(&rv->combined_buffer, data);
|
||||
IMB_assign_float_buffer(rv_ibuf, data, IB_TAKE_OWNERSHIP);
|
||||
}
|
||||
|
||||
memcpy(rv->combined_buffer.data,
|
||||
memcpy(rv_ibuf->float_buffer.data,
|
||||
ibuf->float_buffer.data,
|
||||
sizeof(float[4]) * rr->rectx * rr->recty);
|
||||
|
||||
/* TSK! Since sequence render doesn't free the *rr render result, the old rect32
|
||||
* can hang around when sequence render has rendered a 32 bits one before */
|
||||
RE_RenderByteBuffer_data_free(&rv->byte_buffer);
|
||||
imb_freerectImBuf(rv_ibuf);
|
||||
}
|
||||
else if (ibuf->byte_buffer.data) {
|
||||
rr->have_combined = true;
|
||||
|
||||
if (!rv->byte_buffer.data) {
|
||||
if (!rv_ibuf->byte_buffer.data) {
|
||||
uint8_t *data = MEM_cnew_array<uint8_t>(4 * rr->rectx * rr->recty, "render_seq rect");
|
||||
RE_RenderByteBuffer_assign_data(&rv->byte_buffer, data);
|
||||
IMB_assign_byte_buffer(rv_ibuf, data, IB_TAKE_OWNERSHIP);
|
||||
}
|
||||
|
||||
memcpy(rv->byte_buffer.data, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
|
||||
memcpy(rv_ibuf->byte_buffer.data, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
|
||||
|
||||
/* Same things as above, old rectf can hang around from previous render. */
|
||||
RE_RenderBuffer_data_free(&rv->combined_buffer);
|
||||
imb_freerectfloatImBuf(rv_ibuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1076,15 +1112,20 @@ void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
|
|||
{
|
||||
RenderView *rv = RE_RenderViewGetById(rr, view_id);
|
||||
|
||||
if (rv->combined_buffer.data) {
|
||||
memset(rv->combined_buffer.data, 0, sizeof(float[4]) * rr->rectx * rr->recty);
|
||||
}
|
||||
else if (rv->byte_buffer.data) {
|
||||
memset(rv->byte_buffer.data, 0, 4 * rr->rectx * rr->recty);
|
||||
}
|
||||
else {
|
||||
ImBuf *ibuf = RE_RenderViewEnsureImBuf(rr, rv);
|
||||
|
||||
if (!ibuf->float_buffer.data && !ibuf->byte_buffer.data) {
|
||||
uint8_t *data = MEM_cnew_array<uint8_t>(rr->rectx * rr->recty, "render_seq rect");
|
||||
RE_RenderByteBuffer_assign_data(&rv->byte_buffer, data);
|
||||
IMB_assign_byte_buffer(ibuf, data, IB_TAKE_OWNERSHIP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ibuf->float_buffer.data) {
|
||||
memset(ibuf->float_buffer.data, 0, sizeof(float[4]) * rr->rectx * rr->recty);
|
||||
}
|
||||
|
||||
if (ibuf->byte_buffer.data) {
|
||||
memset(ibuf->byte_buffer.data, 0, 4 * rr->rectx * rr->recty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1097,13 +1138,14 @@ void render_result_rect_get_pixels(RenderResult *rr,
|
|||
const int view_id)
|
||||
{
|
||||
RenderView *rv = RE_RenderViewGetById(rr, view_id);
|
||||
ImBuf *ibuf = rv ? rv->ibuf : nullptr;
|
||||
|
||||
if (rv && rv->byte_buffer.data) {
|
||||
memcpy(rect, rv->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
|
||||
if (ibuf->byte_buffer.data) {
|
||||
|
||||
memcpy(rect, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
|
||||
}
|
||||
else if (rv && rv->combined_buffer.data) {
|
||||
else if (ibuf->float_buffer.data) {
|
||||
IMB_display_buffer_transform_apply((uchar *)rect,
|
||||
rv->combined_buffer.data,
|
||||
ibuf->float_buffer.data,
|
||||
rr->rectx,
|
||||
rr->recty,
|
||||
4,
|
||||
|
@ -1130,13 +1172,17 @@ bool RE_HasCombinedLayer(const RenderResult *result)
|
|||
return false;
|
||||
}
|
||||
|
||||
return (rv->byte_buffer.data || rv->combined_buffer.data);
|
||||
return (rv->ibuf);
|
||||
}
|
||||
|
||||
bool RE_HasFloatPixels(const RenderResult *result)
|
||||
{
|
||||
LISTBASE_FOREACH (const RenderView *, rview, &result->views) {
|
||||
if (rview->byte_buffer.data && !rview->combined_buffer.data) {
|
||||
ImBuf *ibuf = rview->ibuf;
|
||||
if (!ibuf) {
|
||||
continue;
|
||||
}
|
||||
if (ibuf->byte_buffer.data && !ibuf->float_buffer.data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1177,9 +1223,7 @@ static RenderPass *duplicate_render_pass(RenderPass *rpass)
|
|||
RenderPass *new_rpass = MEM_cnew<RenderPass>("new render pass", *rpass);
|
||||
new_rpass->next = new_rpass->prev = nullptr;
|
||||
|
||||
if (new_rpass->buffer.sharing_info != nullptr) {
|
||||
new_rpass->buffer.sharing_info->add_user();
|
||||
}
|
||||
new_rpass->ibuf = IMB_dupImBuf(rpass->ibuf);
|
||||
|
||||
return new_rpass;
|
||||
}
|
||||
|
@ -1201,19 +1245,7 @@ static RenderView *duplicate_render_view(RenderView *rview)
|
|||
{
|
||||
RenderView *new_rview = MEM_cnew<RenderView>("new render view", *rview);
|
||||
|
||||
/* Reset buffers, they are not supposed to be shallow-coped. */
|
||||
new_rview->combined_buffer = {};
|
||||
new_rview->byte_buffer = {};
|
||||
|
||||
if (rview->combined_buffer.data != nullptr) {
|
||||
RE_RenderBuffer_assign_data(&new_rview->combined_buffer,
|
||||
static_cast<float *>(MEM_dupallocN(rview->combined_buffer.data)));
|
||||
}
|
||||
|
||||
if (rview->byte_buffer.data != nullptr) {
|
||||
RE_RenderByteBuffer_assign_data(
|
||||
&new_rview->byte_buffer, static_cast<uint8_t *>(MEM_dupallocN(rview->byte_buffer.data)));
|
||||
}
|
||||
new_rview->ibuf = IMB_dupImBuf(rview->ibuf);
|
||||
|
||||
return new_rview;
|
||||
}
|
||||
|
@ -1233,115 +1265,27 @@ RenderResult *RE_DuplicateRenderResult(RenderResult *rr)
|
|||
BLI_addtail(&new_rr->views, new_rview);
|
||||
}
|
||||
|
||||
/* Reset buffers, they are not supposed to be shallow-coped. */
|
||||
new_rr->combined_buffer = {};
|
||||
new_rr->byte_buffer = {};
|
||||
|
||||
if (rr->combined_buffer.data) {
|
||||
RE_RenderBuffer_assign_data(&new_rr->combined_buffer,
|
||||
static_cast<float *>(MEM_dupallocN(rr->combined_buffer.data)));
|
||||
}
|
||||
if (rr->byte_buffer.data) {
|
||||
RE_RenderByteBuffer_assign_data(&new_rr->byte_buffer,
|
||||
static_cast<uint8_t *>(MEM_dupallocN(rr->byte_buffer.data)));
|
||||
}
|
||||
new_rr->ibuf = IMB_dupImBuf(rr->ibuf);
|
||||
|
||||
new_rr->stamp_data = BKE_stamp_data_copy(new_rr->stamp_data);
|
||||
return new_rr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Render buffer.
|
||||
*/
|
||||
|
||||
template<class BufferType> static BufferType render_buffer_new(decltype(BufferType::data) data)
|
||||
ImBuf *RE_RenderPassEnsureImBuf(RenderPass *render_pass)
|
||||
{
|
||||
BufferType buffer;
|
||||
|
||||
buffer.data = data;
|
||||
buffer.sharing_info = blender::implicit_sharing::info_for_mem_free(data);
|
||||
buffer.gpu_texture = nullptr;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template<class BufferType> static void render_buffer_data_free(BufferType *render_buffer)
|
||||
{
|
||||
if (!render_buffer->sharing_info) {
|
||||
MEM_SAFE_FREE(render_buffer->data);
|
||||
return;
|
||||
if (!render_pass->ibuf) {
|
||||
render_pass->ibuf = IMB_allocImBuf(render_pass->rectx, render_pass->recty, 32, 0);
|
||||
render_pass->ibuf->channels = render_pass->channels;
|
||||
}
|
||||
|
||||
blender::implicit_sharing::free_shared_data(&render_buffer->data, &render_buffer->sharing_info);
|
||||
|
||||
if (render_buffer->gpu_texture) {
|
||||
GPU_texture_free(render_buffer->gpu_texture);
|
||||
render_buffer->gpu_texture = nullptr;
|
||||
}
|
||||
return render_pass->ibuf;
|
||||
}
|
||||
|
||||
template<class BufferType>
|
||||
static void render_buffer_assign_data(BufferType *render_buffer, decltype(BufferType::data) data)
|
||||
ImBuf *RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *render_view)
|
||||
{
|
||||
render_buffer_data_free(render_buffer);
|
||||
|
||||
if (!data) {
|
||||
render_buffer->data = nullptr;
|
||||
render_buffer->sharing_info = nullptr;
|
||||
return;
|
||||
if (!render_view->ibuf) {
|
||||
render_view->ibuf = IMB_allocImBuf(render_result->rectx, render_result->recty, 32, 0);
|
||||
}
|
||||
|
||||
render_buffer->data = data;
|
||||
render_buffer->sharing_info = blender::implicit_sharing::info_for_mem_free(data);
|
||||
}
|
||||
|
||||
template<class BufferType>
|
||||
static void render_buffer_assign_shared(BufferType *lhs, const BufferType *rhs)
|
||||
{
|
||||
render_buffer_data_free(lhs);
|
||||
|
||||
if (rhs) {
|
||||
blender::implicit_sharing::copy_shared_pointer(
|
||||
rhs->data, rhs->sharing_info, &lhs->data, &lhs->sharing_info);
|
||||
}
|
||||
}
|
||||
|
||||
RenderBuffer RE_RenderBuffer_new(float *data)
|
||||
{
|
||||
return render_buffer_new<RenderBuffer>(data);
|
||||
}
|
||||
|
||||
void RE_RenderBuffer_assign_data(RenderBuffer *render_buffer, float *data)
|
||||
{
|
||||
return render_buffer_assign_data(render_buffer, data);
|
||||
}
|
||||
|
||||
void RE_RenderBuffer_assign_shared(RenderBuffer *lhs, const RenderBuffer *rhs)
|
||||
{
|
||||
render_buffer_assign_shared(lhs, rhs);
|
||||
}
|
||||
|
||||
void RE_RenderBuffer_data_free(RenderBuffer *render_buffer)
|
||||
{
|
||||
render_buffer_data_free(render_buffer);
|
||||
}
|
||||
|
||||
RenderByteBuffer RE_RenderByteBuffer_new(uint8_t *data)
|
||||
{
|
||||
return render_buffer_new<RenderByteBuffer>(data);
|
||||
}
|
||||
|
||||
void RE_RenderByteBuffer_assign_data(RenderByteBuffer *render_buffer, uint8_t *data)
|
||||
{
|
||||
return render_buffer_assign_data(render_buffer, data);
|
||||
}
|
||||
|
||||
void RE_RenderByteBuffer_assign_shared(RenderByteBuffer *lhs, const RenderByteBuffer *rhs)
|
||||
{
|
||||
render_buffer_assign_shared(lhs, rhs);
|
||||
}
|
||||
|
||||
void RE_RenderByteBuffer_data_free(RenderByteBuffer *render_buffer)
|
||||
{
|
||||
render_buffer_data_free(render_buffer);
|
||||
}
|
||||
return render_view->ibuf;
|
||||
}
|
|
@ -1577,18 +1577,18 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
|
|||
|
||||
RE_AcquireResultImage(re, &rres, view_id);
|
||||
|
||||
if (rres.combined_buffer.data) {
|
||||
if (rres.ibuf && rres.ibuf->float_buffer.data) {
|
||||
ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, 0);
|
||||
IMB_assign_shared_float_buffer(
|
||||
ibufs_arr[view_id], rres.combined_buffer.data, rres.combined_buffer.sharing_info);
|
||||
IMB_assign_float_buffer(
|
||||
ibufs_arr[view_id], rres.ibuf->float_buffer.data, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
|
||||
/* float buffers in the sequencer are not linear */
|
||||
seq_imbuf_to_sequencer_space(context->scene, ibufs_arr[view_id], false);
|
||||
}
|
||||
else if (rres.byte_buffer.data) {
|
||||
else if (rres.ibuf->byte_buffer.data) {
|
||||
ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
|
||||
memcpy(ibufs_arr[view_id]->byte_buffer.data,
|
||||
rres.byte_buffer.data,
|
||||
rres.ibuf->byte_buffer.data,
|
||||
4 * rres.rectx * rres.recty);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Could be a problem if ibuf is nullptr I think.