Refactor Render Result to allow implicit buffer sharing #108045
|
@ -3989,12 +3989,11 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
|
|||
|
||||
if (rpass) {
|
||||
// printf("load from pass %s\n", rpass->name);
|
||||
/* since we free render results, we copy the rect */
|
||||
ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
|
||||
IMB_assign_float_buffer(
|
||||
ibuf, static_cast<float *>(MEM_dupallocN(rpass->rect)), IB_TAKE_OWNERSHIP);
|
||||
ibuf->channels = rpass->channels;
|
||||
|
||||
IMB_assign_shared_float_buffer(ibuf, rpass->buffer.data, rpass->buffer.sharing_info);
|
||||
|
||||
BKE_imbuf_stamp_info(ima->rr, ibuf);
|
||||
|
||||
image_init_after_load(ima, iuser, ibuf);
|
||||
|
@ -4301,7 +4300,8 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
|
|||
|
||||
image_init_after_load(ima, iuser, ibuf);
|
||||
|
||||
IMB_assign_float_buffer(ibuf, rpass->rect, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
IMB_assign_shared_float_buffer(ibuf, rpass->buffer.data, rpass->buffer.sharing_info);
|
||||
|
||||
ibuf->channels = rpass->channels;
|
||||
|
||||
BKE_imbuf_stamp_info(ima->rr, ibuf);
|
||||
|
@ -4320,8 +4320,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
{
|
||||
Render *re;
|
||||
RenderView *rv;
|
||||
float *rectf, *rectz;
|
||||
uint *rect;
|
||||
RenderBuffer *combined_buffer, *z_buffer;
|
||||
RenderByteBuffer *byte_buffer;
|
||||
float dither;
|
||||
int channels, layer, pass;
|
||||
ImBuf *ibuf;
|
||||
|
@ -4355,7 +4355,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)->rectf != nullptr;
|
||||
rres.have_combined = ((RenderView *)rres.views.first)->combined_buffer.data != nullptr;
|
||||
}
|
||||
|
||||
if (!(rres.rectx > 0 && rres.recty > 0)) {
|
||||
|
@ -4380,14 +4380,14 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
|
||||
/* this gives active layer, composite or sequence result */
|
||||
if (rv == nullptr) {
|
||||
rect = (uint *)rres.rect32;
|
||||
rectf = rres.rectf;
|
||||
rectz = rres.rectz;
|
||||
byte_buffer = &rres.byte_buffer;
|
||||
combined_buffer = &rres.combined_buffer;
|
||||
z_buffer = &rres.z_buffer;
|
||||
}
|
||||
else {
|
||||
rect = (uint *)rv->rect32;
|
||||
rectf = rv->rectf;
|
||||
rectz = rv->rectz;
|
||||
byte_buffer = &rv->byte_buffer;
|
||||
combined_buffer = &rv->combined_buffer;
|
||||
z_buffer = &rv->z_buffer;
|
||||
}
|
||||
|
||||
dither = iuser->scene->r.dither_intensity;
|
||||
|
@ -4396,13 +4396,13 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
if (rres.have_combined && layer == 0) {
|
||||
/* pass */
|
||||
}
|
||||
else if (rect && layer == 0) {
|
||||
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
|
||||
*/
|
||||
rectf = nullptr;
|
||||
combined_buffer = nullptr;
|
||||
}
|
||||
else if (rres.layers.first) {
|
||||
RenderLayer *rl = static_cast<RenderLayer *>(
|
||||
|
@ -4410,7 +4410,7 @@ 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) {
|
||||
rectf = rpass->rect;
|
||||
combined_buffer = &rpass->buffer;
|
||||
if (pass != 0) {
|
||||
channels = rpass->channels;
|
||||
dither = 0.0f; /* don't dither passes */
|
||||
|
@ -4419,7 +4419,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
|
||||
for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass; rpass = rpass->next) {
|
||||
if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) {
|
||||
rectz = rpass->rect;
|
||||
z_buffer = &rpass->buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4441,14 +4441,16 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
*
|
||||
* For other cases we need to be sure it stays to default byte buffer space.
|
||||
*/
|
||||
if (ibuf->byte_buffer.data != (uint8_t *)rect) {
|
||||
if (ibuf->byte_buffer.data != byte_buffer->data) {
|
||||
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
|
||||
IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace);
|
||||
}
|
||||
|
||||
/* invalidate color managed buffers if render result changed */
|
||||
BLI_thread_lock(LOCK_COLORMANAGE);
|
||||
if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->float_buffer.data != rectf) {
|
||||
if (combined_buffer && (ibuf->x != rres.rectx || ibuf->y != rres.recty ||
|
||||
ibuf->float_buffer.data != combined_buffer->data))
|
||||
{
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
}
|
||||
|
||||
|
@ -4458,9 +4460,26 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
|
||||
imb_freerectImBuf(ibuf);
|
||||
|
||||
IMB_assign_byte_buffer(ibuf, (uint8_t *)rect, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
IMB_assign_float_buffer(ibuf, rectf, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
IMB_assign_float_z_buffer(ibuf, rectz, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
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);
|
||||
}
|
||||
|
||||
if (z_buffer) {
|
||||
IMB_assign_shared_float_z_buffer(ibuf, z_buffer->data, z_buffer->sharing_info);
|
||||
}
|
||||
else {
|
||||
IMB_assign_float_z_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
|
||||
|
|
|
@ -738,7 +738,7 @@ bool BKE_image_render_write_exr(ReportList *reports,
|
|||
/* Compositing result. */
|
||||
if (rr->have_combined) {
|
||||
LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
|
||||
if (!rview->rectf) {
|
||||
if (!rview->combined_buffer.data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -756,10 +756,11 @@ bool BKE_image_render_write_exr(ReportList *reports,
|
|||
continue;
|
||||
}
|
||||
|
||||
float *output_rect = (save_as_render) ?
|
||||
float *output_rect =
|
||||
(save_as_render) ?
|
||||
image_exr_from_scene_linear_to_output(
|
||||
rview->rectf, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
|
||||
rview->rectf;
|
||||
rview->combined_buffer.data, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
|
||||
rview->combined_buffer.data;
|
||||
|
||||
for (int a = 0; a < channels; a++) {
|
||||
char passname[EXR_PASS_MAXNAME];
|
||||
|
@ -781,9 +782,10 @@ bool BKE_image_render_write_exr(ReportList *reports,
|
|||
exrhandle, layname, passname, viewname, 4, 4 * rr->rectx, output_rect + a, half_float);
|
||||
}
|
||||
|
||||
if (write_z && rview->rectz) {
|
||||
if (write_z && rview->z_buffer.data) {
|
||||
const char *layname = (multi_layer) ? "Composite" : "";
|
||||
IMB_exr_add_channel(exrhandle, layname, "Z", viewname, 1, rr->rectx, rview->rectz, false);
|
||||
IMB_exr_add_channel(
|
||||
exrhandle, layname, "Z", viewname, 1, rr->rectx, rview->z_buffer.data, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -825,8 +827,8 @@ bool BKE_image_render_write_exr(ReportList *reports,
|
|||
float *output_rect =
|
||||
(save_as_render && pass_RGBA) ?
|
||||
image_exr_from_scene_linear_to_output(
|
||||
rp->rect, rr->rectx, rr->recty, rp->channels, imf, tmp_output_rects) :
|
||||
rp->rect;
|
||||
rp->buffer.data, rr->rectx, rr->recty, rp->channels, imf, tmp_output_rects) :
|
||||
rp->buffer.data;
|
||||
|
||||
for (int a = 0; a < std::min(channels, rp->channels); a++) {
|
||||
/* Save Combined as RGBA or RGB if single layer save. */
|
||||
|
|
|
@ -67,14 +67,9 @@ void CompositorOperation::deinit_execution()
|
|||
if (rr) {
|
||||
RenderView *rv = RE_RenderViewGetByName(rr, view_name_);
|
||||
|
||||
if (rv->rectf != nullptr) {
|
||||
MEM_freeN(rv->rectf);
|
||||
}
|
||||
rv->rectf = output_buffer_;
|
||||
if (rv->rectz != nullptr) {
|
||||
MEM_freeN(rv->rectz);
|
||||
}
|
||||
rv->rectz = depth_buffer_;
|
||||
RE_RenderBuffer_assign_data(&rv->combined_buffer, output_buffer_);
|
||||
RE_RenderBuffer_assign_data(&rv->z_buffer, depth_buffer_);
|
||||
|
||||
rr->have_combined = true;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -582,6 +582,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;
|
||||
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 +
|
||||
|
@ -589,15 +590,15 @@ static void eevee_cryptomatte_extract_render_passes(
|
|||
accum_pixel_stride +
|
||||
layer_index * layer_stride + pass_offset;
|
||||
const int render_pass_offset = (y * rect_width + x) * 4;
|
||||
rp_object->rect[render_pass_offset] = accum_buffer[accum_buffer_offset].hash;
|
||||
rp_object->rect[render_pass_offset + 1] = accum_buffer[accum_buffer_offset].weight;
|
||||
rp_buffer_data[render_pass_offset] = accum_buffer[accum_buffer_offset].hash;
|
||||
rp_buffer_data[render_pass_offset + 1] = accum_buffer[accum_buffer_offset].weight;
|
||||
if (levels_done + 1 < num_cryptomatte_levels) {
|
||||
rp_object->rect[render_pass_offset + 2] = accum_buffer[accum_buffer_offset + 1].hash;
|
||||
rp_object->rect[render_pass_offset + 3] = accum_buffer[accum_buffer_offset + 1].weight;
|
||||
rp_buffer_data[render_pass_offset + 2] = accum_buffer[accum_buffer_offset + 1].hash;
|
||||
rp_buffer_data[render_pass_offset + 3] = accum_buffer[accum_buffer_offset + 1].weight;
|
||||
}
|
||||
else {
|
||||
rp_object->rect[render_pass_offset + 2] = 0.0f;
|
||||
rp_object->rect[render_pass_offset + 3] = 0.0f;
|
||||
rp_buffer_data[render_pass_offset + 2] = 0.0f;
|
||||
rp_buffer_data[render_pass_offset + 3] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ static void eevee_render_color_result(RenderLayer *rl,
|
|||
num_channels,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->rect);
|
||||
rp->buffer.data);
|
||||
}
|
||||
|
||||
static void eevee_render_result_combined(RenderLayer *rl,
|
||||
|
|
|
@ -276,8 +276,7 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na
|
|||
* However, on some implementation, we need a buffer with a few extra bytes for the read to
|
||||
* happen correctly (see GLTexture::read()). So we need a custom memory allocation. */
|
||||
/* Avoid memcpy(), replace the pointer directly. */
|
||||
MEM_SAFE_FREE(rp->rect);
|
||||
rp->rect = result;
|
||||
RE_pass_set_buffer_data(rp, result);
|
||||
BLI_mutex_unlock(&render->update_render_passes_mutex);
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +290,7 @@ 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->rect, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
|
||||
memset(vector_rp->buffer.data, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,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->rect : NULL;
|
||||
float *pix_col = (rpass_col_src) ? rpass_col_src->rect : NULL;
|
||||
float *pix_z = (rpass_z_src) ? rpass_z_src->buffer.data : NULL;
|
||||
float *pix_col = (rpass_col_src) ? rpass_col_src->buffer.data : NULL;
|
||||
|
||||
if (!pix_z || !pix_col) {
|
||||
RE_engine_set_error_message(engine,
|
||||
|
@ -160,6 +160,7 @@ static void GPENCIL_render_result_z(struct 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;
|
||||
|
||||
GPU_framebuffer_read_depth(vedata->fbl->render_fb,
|
||||
rect->xmin,
|
||||
|
@ -167,7 +168,7 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
|
|||
BLI_rcti_size_x(rect),
|
||||
BLI_rcti_size_y(rect),
|
||||
GPU_DATA_FLOAT,
|
||||
rp->rect);
|
||||
ro_buffer_data);
|
||||
|
||||
float winmat[4][4];
|
||||
DRW_view_winmat_get(NULL, winmat, false);
|
||||
|
@ -177,12 +178,12 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
|
|||
/* Convert GPU depth [0..1] to view Z [near..far] */
|
||||
if (DRW_view_is_persp_get(NULL)) {
|
||||
for (int i = 0; i < pix_num; i++) {
|
||||
if (rp->rect[i] == 1.0f) {
|
||||
rp->rect[i] = 1e10f; /* Background */
|
||||
if (ro_buffer_data[i] == 1.0f) {
|
||||
ro_buffer_data[i] = 1e10f; /* Background */
|
||||
}
|
||||
else {
|
||||
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
|
||||
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
|
||||
ro_buffer_data[i] = ro_buffer_data[i] * 2.0f - 1.0f;
|
||||
ro_buffer_data[i] = winmat[3][2] / (ro_buffer_data[i] + winmat[2][2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,11 +194,11 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
|
|||
float range = fabsf(far - near);
|
||||
|
||||
for (int i = 0; i < pix_num; i++) {
|
||||
if (rp->rect[i] == 1.0f) {
|
||||
rp->rect[i] = 1e10f; /* Background */
|
||||
if (ro_buffer_data[i] == 1.0f) {
|
||||
ro_buffer_data[i] = 1e10f; /* Background */
|
||||
}
|
||||
else {
|
||||
rp->rect[i] = rp->rect[i] * range - near;
|
||||
ro_buffer_data[i] = ro_buffer_data[i] * range - near;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +222,7 @@ static void GPENCIL_render_result_combined(struct RenderLayer *rl,
|
|||
4,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->rect);
|
||||
rp->buffer.data);
|
||||
}
|
||||
|
||||
void GPENCIL_render_to_image(void *ved,
|
||||
|
|
|
@ -552,7 +552,7 @@ static void write_render_color_output(struct RenderLayer *layer,
|
|||
4,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->rect);
|
||||
rp->buffer.data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,13 +571,13 @@ static void write_render_z_output(struct RenderLayer *layer,
|
|||
BLI_rcti_size_x(rect),
|
||||
BLI_rcti_size_y(rect),
|
||||
GPU_DATA_FLOAT,
|
||||
rp->rect);
|
||||
rp->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->rect, pix_num)) {
|
||||
for (float &z : MutableSpan(rp->buffer.data, pix_num)) {
|
||||
if (z == 1.0f) {
|
||||
z = 1e10f; /* Background */
|
||||
}
|
||||
|
@ -593,7 +593,7 @@ static void write_render_z_output(struct RenderLayer *layer,
|
|||
float far = DRW_view_far_distance_get(nullptr);
|
||||
float range = fabsf(far - near);
|
||||
|
||||
for (float &z : MutableSpan(rp->rect, pix_num)) {
|
||||
for (float &z : MutableSpan(rp->buffer.data, pix_num)) {
|
||||
if (z == 1.0f) {
|
||||
z = 1e10f; /* Background */
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ static void workbench_render_result_z(struct RenderLayer *rl,
|
|||
|
||||
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;
|
||||
|
||||
GPU_framebuffer_bind(dfbl->default_fb);
|
||||
GPU_framebuffer_read_depth(dfbl->default_fb,
|
||||
|
@ -113,7 +114,7 @@ static void workbench_render_result_z(struct RenderLayer *rl,
|
|||
BLI_rcti_size_x(rect),
|
||||
BLI_rcti_size_y(rect),
|
||||
GPU_DATA_FLOAT,
|
||||
rp->rect);
|
||||
rp_buffer_data);
|
||||
|
||||
float winmat[4][4];
|
||||
DRW_view_winmat_get(NULL, winmat, false);
|
||||
|
@ -123,12 +124,12 @@ static void workbench_render_result_z(struct RenderLayer *rl,
|
|||
/* Convert GPU depth [0..1] to view Z [near..far] */
|
||||
if (DRW_view_is_persp_get(NULL)) {
|
||||
for (int i = 0; i < pix_num; i++) {
|
||||
if (rp->rect[i] == 1.0f) {
|
||||
rp->rect[i] = 1e10f; /* Background */
|
||||
if (rp_buffer_data[i] == 1.0f) {
|
||||
rp_buffer_data[i] = 1e10f; /* Background */
|
||||
}
|
||||
else {
|
||||
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
|
||||
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
|
||||
rp_buffer_data[i] = rp_buffer_data[i] * 2.0f - 1.0f;
|
||||
rp_buffer_data[i] = winmat[3][2] / (rp_buffer_data[i] + winmat[2][2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,11 +140,11 @@ static void workbench_render_result_z(struct RenderLayer *rl,
|
|||
float range = fabsf(far - near);
|
||||
|
||||
for (int i = 0; i < pix_num; i++) {
|
||||
if (rp->rect[i] == 1.0f) {
|
||||
rp->rect[i] = 1e10f; /* Background */
|
||||
if (rp_buffer_data[i] == 1.0f) {
|
||||
rp_buffer_data[i] = 1e10f; /* Background */
|
||||
}
|
||||
else {
|
||||
rp->rect[i] = rp->rect[i] * range - near;
|
||||
rp_buffer_data[i] = rp_buffer_data[i] * range - near;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +209,7 @@ void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer
|
|||
4,
|
||||
0,
|
||||
GPU_DATA_FLOAT,
|
||||
rp->rect);
|
||||
rp->buffer.data);
|
||||
|
||||
workbench_render_result_z(render_layer, viewname, rect);
|
||||
}
|
||||
|
|
|
@ -181,7 +181,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->rect[offset];
|
||||
r_col[0] = render_pass->buffer.data[offset];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,11 +207,11 @@ static void image_buffer_rect_update(RenderJob *rj,
|
|||
rv = RE_RenderViewGetById(rr, view_id);
|
||||
|
||||
/* find current float rect for display, first case is after composite... still weak */
|
||||
if (rv->rectf) {
|
||||
rectf = rv->rectf;
|
||||
if (rv->combined_buffer.data) {
|
||||
rectf = rv->combined_buffer.data;
|
||||
}
|
||||
else {
|
||||
if (rv->rect32) {
|
||||
if (rv->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)
|
||||
|
|
|
@ -193,17 +193,9 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
|
|||
RenderView *rv_del = rv->next;
|
||||
BLI_remlink(&rr->views, rv_del);
|
||||
|
||||
if (rv_del->rectf) {
|
||||
MEM_freeN(rv_del->rectf);
|
||||
}
|
||||
|
||||
if (rv_del->rectz) {
|
||||
MEM_freeN(rv_del->rectz);
|
||||
}
|
||||
|
||||
if (rv_del->rect32) {
|
||||
MEM_freeN(rv_del->rect32);
|
||||
}
|
||||
RE_RenderBuffer_data_free(&rv_del->combined_buffer);
|
||||
RE_RenderBuffer_data_free(&rv_del->z_buffer);
|
||||
RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
|
||||
|
||||
MEM_freeN(rv_del);
|
||||
}
|
||||
|
@ -227,17 +219,9 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
|
|||
|
||||
BLI_remlink(&rr->views, rv_del);
|
||||
|
||||
if (rv_del->rectf) {
|
||||
MEM_freeN(rv_del->rectf);
|
||||
}
|
||||
|
||||
if (rv_del->rectz) {
|
||||
MEM_freeN(rv_del->rectz);
|
||||
}
|
||||
|
||||
if (rv_del->rect32) {
|
||||
MEM_freeN(rv_del->rect32);
|
||||
}
|
||||
RE_RenderBuffer_data_free(&rv_del->combined_buffer);
|
||||
RE_RenderBuffer_data_free(&rv_del->z_buffer);
|
||||
RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
|
||||
|
||||
MEM_freeN(rv_del);
|
||||
}
|
||||
|
|
|
@ -666,7 +666,7 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect
|
|||
rv = nullptr;
|
||||
}
|
||||
|
||||
if (rv && rv->rectf) {
|
||||
if (rv && rv->combined_buffer.data) {
|
||||
|
||||
if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) {
|
||||
|
||||
|
@ -1073,8 +1073,9 @@ 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;
|
||||
rv->rectf = static_cast<float *>(
|
||||
MEM_callocN(sizeof(float[4]) * width * height, "texture render result"));
|
||||
RE_RenderBuffer_assign_data(&rv->combined_buffer,
|
||||
static_cast<float *>(MEM_callocN(sizeof(float[4]) * width * height,
|
||||
"texture render result")));
|
||||
RE_ReleaseResult(re);
|
||||
|
||||
/* Get texture image pool (if any) */
|
||||
|
@ -1082,7 +1083,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->rectf;
|
||||
float *rect_float = rv->combined_buffer.data;
|
||||
float tex_coord[3] = {0.0f, 0.0f, 0.0f};
|
||||
bool color_manage = true;
|
||||
|
||||
|
|
|
@ -127,10 +127,10 @@ 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->rectf) {
|
||||
if (rv->combined_buffer.data) {
|
||||
return IFACE_("Composite");
|
||||
}
|
||||
if (rv->rect32) {
|
||||
if (rv->byte_buffer.data) {
|
||||
return IFACE_("Sequence");
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -445,12 +445,13 @@ 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;
|
||||
if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE_COLOR)) {
|
||||
controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty);
|
||||
controller->setPassDiffuse(rpass_buffer_data, rpass->rectx, rpass->recty);
|
||||
diffuse = true;
|
||||
}
|
||||
if (STREQ(rpass->name, RE_PASSNAME_Z)) {
|
||||
controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty);
|
||||
controller->setPassZ(rpass_buffer_data, rpass->rectx, rpass->recty);
|
||||
z = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "../blenlib/BLI_sys_types.h"
|
||||
#include "../gpu/GPU_texture.h"
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -148,6 +149,20 @@ 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 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);
|
||||
void IMB_assign_shared_float_z_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.
|
||||
*
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
|
||||
#include "DNA_vec_types.h" /* for rcti */
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
@ -169,22 +171,31 @@ typedef enum ImBufOwnership {
|
|||
IB_TAKE_OWNERSHIP = 1,
|
||||
} ImBufOwnership;
|
||||
|
||||
/* Different storage specialization. */
|
||||
/* Different storage specialization.
|
||||
*
|
||||
* Note on the implicit sharing
|
||||
* ----------------------------
|
||||
*
|
||||
* 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. */
|
||||
|
||||
typedef struct ImBufIntBuffer {
|
||||
int *data;
|
||||
ImBufOwnership ownership;
|
||||
const ImplicitSharingInfoHandle *implicit_sharing;
|
||||
} ImBufIntBuffer;
|
||||
|
||||
typedef struct ImBufByteBuffer {
|
||||
uint8_t *data;
|
||||
ImBufOwnership ownership;
|
||||
const ImplicitSharingInfoHandle *implicit_sharing;
|
||||
} ImBufByteBuffer;
|
||||
|
||||
typedef struct ImBufFloatBuffer {
|
||||
float *data;
|
||||
ImBufOwnership ownership;
|
||||
const ImplicitSharingInfoHandle *implicit_sharing;
|
||||
} ImBufFloatBuffer;
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_implicit_sharing.hh"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -65,12 +66,16 @@ void imb_mmap_unlock(void)
|
|||
* buffer to its defaults. */
|
||||
template<class BufferType> static void imb_free_buffer(BufferType &buffer)
|
||||
{
|
||||
if (buffer.data) {
|
||||
if (buffer.implicit_sharing) {
|
||||
blender::implicit_sharing::free_shared_data(&buffer.data, &buffer.implicit_sharing);
|
||||
}
|
||||
else 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;
|
||||
}
|
||||
|
@ -79,6 +84,7 @@ 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.
|
||||
|
@ -110,6 +116,11 @@ template<class BufferType> void imb_make_writeable_buffer(BufferType &buffer)
|
|||
case IB_DO_NOT_TAKE_OWNERSHIP:
|
||||
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:
|
||||
|
@ -144,6 +155,30 @@ 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;
|
||||
|
@ -483,6 +518,45 @@ 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_shared_float_z_buffer(ImBuf *ibuf,
|
||||
float *buffer_data,
|
||||
const ImplicitSharingInfoHandle *implicit_sharing)
|
||||
{
|
||||
imb_free_buffer(ibuf->float_z_buffer);
|
||||
ibuf->flags &= ~IB_zbuffloat;
|
||||
|
||||
if (buffer_data) {
|
||||
imb_assign_shared_buffer(ibuf->float_z_buffer, buffer_data, implicit_sharing);
|
||||
ibuf->flags |= IB_zbuffloat;
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, const ImBufOwnership ownership)
|
||||
{
|
||||
imb_free_buffer(ibuf->byte_buffer);
|
||||
|
|
|
@ -503,13 +503,15 @@ 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->rect, sizeof(float) * rpass->rectx * rpass->recty * rpass->channels);
|
||||
memcpy(
|
||||
values, rpass->buffer.data, sizeof(float) * rpass->rectx * rpass->recty * rpass->channels);
|
||||
}
|
||||
|
||||
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values)
|
||||
{
|
||||
RenderPass *rpass = (RenderPass *)ptr->data;
|
||||
memcpy(rpass->rect, values, sizeof(float) * rpass->rectx * rpass->recty * rpass->channels);
|
||||
memcpy(
|
||||
rpass->buffer.data, values, sizeof(float) * rpass->rectx * rpass->recty * rpass->channels);
|
||||
}
|
||||
|
||||
static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, const char *view)
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "DNA_listBase.h"
|
||||
#include "DNA_vec_types.h"
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
|
||||
struct ImBuf;
|
||||
struct Image;
|
||||
struct ImageFormatData;
|
||||
|
@ -38,6 +40,21 @@ 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. */
|
||||
typedef struct RenderBuffer {
|
||||
float *data;
|
||||
const ImplicitSharingInfoHandle *sharing_info;
|
||||
} RenderBuffer;
|
||||
|
||||
/* Specialized render buffer to store 8bpp passes. */
|
||||
typedef struct RenderByteBuffer {
|
||||
uint8_t *data;
|
||||
const ImplicitSharingInfoHandle *sharing_info;
|
||||
} RenderByteBuffer;
|
||||
|
||||
/* Render Result usage:
|
||||
*
|
||||
* - render engine allocates/frees and delivers raw floating point rects
|
||||
|
@ -51,11 +68,11 @@ typedef struct RenderView {
|
|||
char name[64]; /* EXR_VIEW_MAXNAME */
|
||||
|
||||
/* if this exists, result of composited layers */
|
||||
float *rectf;
|
||||
/* if this exists, result of composited layers */
|
||||
float *rectz;
|
||||
RenderBuffer combined_buffer;
|
||||
RenderBuffer z_buffer;
|
||||
|
||||
/* optional, 32 bits version of picture, used for sequencer, OpenGL render and image curves */
|
||||
int *rect32;
|
||||
RenderByteBuffer byte_buffer;
|
||||
|
||||
} RenderView;
|
||||
|
||||
|
@ -64,7 +81,9 @@ typedef struct RenderPass {
|
|||
int channels;
|
||||
char name[64]; /* amount defined in IMB_openexr.h */
|
||||
char chan_id[8]; /* amount defined in IMB_openexr.h */
|
||||
float *rect;
|
||||
|
||||
RenderBuffer buffer;
|
||||
|
||||
int rectx, recty;
|
||||
|
||||
char fullname[64]; /* EXR_PASS_MAXNAME */
|
||||
|
@ -102,15 +121,15 @@ typedef struct RenderResult {
|
|||
/* target image size */
|
||||
int rectx, recty;
|
||||
|
||||
/* The following rect32, rectf and rectz buffers are for temporary storage only,
|
||||
/* 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. */
|
||||
int *rect32;
|
||||
RenderByteBuffer byte_buffer;
|
||||
|
||||
/* if this exists, a copy of one of layers, or result of composited layers */
|
||||
float *rectf;
|
||||
/* if this exists, a copy of one of layers, or result of composited layers */
|
||||
float *rectz;
|
||||
RenderBuffer combined_buffer;
|
||||
RenderBuffer z_buffer;
|
||||
|
||||
/* coordinates within final image (after cropping) */
|
||||
rcti tilerect;
|
||||
|
@ -259,6 +278,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);
|
||||
|
||||
bool RE_HasSingleLayer(struct Render *re);
|
||||
|
||||
|
@ -433,6 +455,13 @@ struct RenderPass *RE_pass_find_by_type(struct RenderLayer *rl,
|
|||
int passtype,
|
||||
const char *viewname);
|
||||
|
||||
/**
|
||||
* Set the buffer data of the render pass.
|
||||
* The pass takes ownership of the data, and creates an implicit sharing handle to allow its
|
||||
* sharing with other users.
|
||||
*/
|
||||
void RE_pass_set_buffer_data(struct RenderPass *pass, float *data);
|
||||
|
||||
/* shaded view or baking options */
|
||||
#define RE_BAKE_NORMALS 0
|
||||
#define RE_BAKE_DISPLACEMENT 1
|
||||
|
@ -467,6 +496,43 @@ 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 ths will share the same buffer as the ths (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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -222,8 +222,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->rect + offset;
|
||||
float *differential = differential_pass->rect + offset;
|
||||
float *primitive = primitive_pass->buffer.data + offset;
|
||||
float *differential = differential_pass->buffer.data + offset;
|
||||
|
||||
size_t bake_offset = (y + ty) * image->width + x;
|
||||
const BakePixel *bake_pixel = pixels + bake_offset;
|
||||
|
@ -290,7 +290,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->rect + offset * channels_num;
|
||||
const float *pass_rect = rpass->buffer.data + offset * channels_num;
|
||||
const BakePixel *bake_pixel = pixels + bake_offset;
|
||||
float *bake_result = result + bake_offset * channels_num;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_implicit_sharing.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_path_util.h"
|
||||
|
@ -225,10 +226,18 @@ void RE_FreeRenderResult(RenderResult *rr)
|
|||
render_result_free(rr);
|
||||
}
|
||||
|
||||
RenderBuffer *RE_RenderLayerGetPassBuffer(struct RenderLayer *rl,
|
||||
const char *name,
|
||||
const char *viewname)
|
||||
{
|
||||
RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname);
|
||||
return rpass ? &rpass->buffer : 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->rect : nullptr;
|
||||
return rpass ? rpass->buffer.data : nullptr;
|
||||
}
|
||||
|
||||
RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
|
||||
|
@ -371,21 +380,31 @@ 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->rectf != nullptr);
|
||||
rr->have_combined = (rv->combined_buffer.data != nullptr);
|
||||
|
||||
/* single layer */
|
||||
RenderLayer *rl = render_get_single_layer(re, re->result);
|
||||
|
||||
/* 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. */
|
||||
|
||||
if (rl) {
|
||||
if (rv->rectf == nullptr) {
|
||||
if (rv->combined_buffer.data == nullptr) {
|
||||
LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
|
||||
rview->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rview->name);
|
||||
RenderBuffer *buffer = RE_RenderLayerGetPassBuffer(
|
||||
rl, RE_PASSNAME_COMBINED, rview->name);
|
||||
if (buffer) {
|
||||
rview->combined_buffer = *buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rv->rectz == nullptr) {
|
||||
if (rv->z_buffer.data == nullptr) {
|
||||
LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
|
||||
rview->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rview->name);
|
||||
RenderBuffer *buffer = RE_RenderLayerGetPassBuffer(rl, RE_PASSNAME_Z, rview->name);
|
||||
if (buffer) {
|
||||
rview->z_buffer = *buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,22 +443,32 @@ 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->rectf != nullptr);
|
||||
rr->have_combined = (rv->combined_buffer.data != nullptr);
|
||||
|
||||
rr->rectf = rv->rectf;
|
||||
rr->rectz = rv->rectz;
|
||||
rr->rect32 = rv->rect32;
|
||||
/* 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->z_buffer = rv->z_buffer;
|
||||
rr->byte_buffer = rv->byte_buffer;
|
||||
|
||||
/* active layer */
|
||||
rl = render_get_single_layer(re, re->result);
|
||||
|
||||
if (rl) {
|
||||
if (rv->rectf == nullptr) {
|
||||
rr->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rv->name);
|
||||
if (rv->combined_buffer.data == nullptr) {
|
||||
RenderBuffer *buffer = RE_RenderLayerGetPassBuffer(rl, RE_PASSNAME_COMBINED, rv->name);
|
||||
if (buffer) {
|
||||
rr->combined_buffer = *buffer;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv->rectz == nullptr) {
|
||||
rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name);
|
||||
if (rv->z_buffer.data == nullptr) {
|
||||
RenderBuffer *buffer = RE_RenderLayerGetPassBuffer(rl, RE_PASSNAME_Z, rv->name);
|
||||
if (buffer) {
|
||||
rr->z_buffer = *buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1198,8 +1227,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,
|
||||
(uchar *)rres.rect32,
|
||||
rres.rectf,
|
||||
rres.byte_buffer.data,
|
||||
rres.combined_buffer.data,
|
||||
rres.rectx,
|
||||
rres.recty,
|
||||
4);
|
||||
|
@ -2464,7 +2493,9 @@ void RE_layer_load_from_file(
|
|||
IMB_float_from_rect(ibuf);
|
||||
}
|
||||
|
||||
memcpy(rpass->rect, ibuf->float_buffer.data, sizeof(float[4]) * layer->rectx * layer->recty);
|
||||
memcpy(rpass->buffer.data,
|
||||
ibuf->float_buffer.data,
|
||||
sizeof(float[4]) * layer->rectx * layer->recty);
|
||||
}
|
||||
else {
|
||||
if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) {
|
||||
|
@ -2478,7 +2509,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->rect,
|
||||
memcpy(rpass->buffer.data,
|
||||
ibuf_clip->float_buffer.data,
|
||||
sizeof(float[4]) * layer->rectx * layer->recty);
|
||||
IMB_freeImBuf(ibuf_clip);
|
||||
|
@ -2605,9 +2636,9 @@ 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) {
|
||||
if (rp->rect) {
|
||||
MEM_freeN(rp->rect);
|
||||
}
|
||||
rp->buffer.sharing_info->remove_user_and_delete_if_last();
|
||||
rp->buffer.sharing_info = nullptr;
|
||||
|
||||
BLI_freelinkN(&rl->passes, rp);
|
||||
}
|
||||
/* create a totally new pass */
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_hash_md5.h"
|
||||
#include "BLI_implicit_sharing.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_rect.h"
|
||||
|
@ -50,17 +51,9 @@ static void render_result_views_free(RenderResult *rr)
|
|||
RenderView *rv = static_cast<RenderView *>(rr->views.first);
|
||||
BLI_remlink(&rr->views, rv);
|
||||
|
||||
if (rv->rect32) {
|
||||
MEM_freeN(rv->rect32);
|
||||
}
|
||||
|
||||
if (rv->rectz) {
|
||||
MEM_freeN(rv->rectz);
|
||||
}
|
||||
|
||||
if (rv->rectf) {
|
||||
MEM_freeN(rv->rectf);
|
||||
}
|
||||
RE_RenderByteBuffer_data_free(&rv->byte_buffer);
|
||||
RE_RenderBuffer_data_free(&rv->combined_buffer);
|
||||
RE_RenderBuffer_data_free(&rv->z_buffer);
|
||||
|
||||
MEM_freeN(rv);
|
||||
}
|
||||
|
@ -79,11 +72,10 @@ void render_result_free(RenderResult *rr)
|
|||
|
||||
while (rl->passes.first) {
|
||||
RenderPass *rpass = static_cast<RenderPass *>(rl->passes.first);
|
||||
if (rpass->rect) {
|
||||
MEM_freeN(rpass->rect);
|
||||
}
|
||||
BLI_remlink(&rl->passes, rpass);
|
||||
MEM_freeN(rpass);
|
||||
|
||||
RE_RenderBuffer_data_free(&rpass->buffer);
|
||||
|
||||
BLI_freelinkN(&rl->passes, rpass);
|
||||
}
|
||||
BLI_remlink(&rr->layers, rl);
|
||||
MEM_freeN(rl);
|
||||
|
@ -91,15 +83,10 @@ void render_result_free(RenderResult *rr)
|
|||
|
||||
render_result_views_free(rr);
|
||||
|
||||
if (rr->rect32) {
|
||||
MEM_freeN(rr->rect32);
|
||||
}
|
||||
if (rr->rectz) {
|
||||
MEM_freeN(rr->rectz);
|
||||
}
|
||||
if (rr->rectf) {
|
||||
MEM_freeN(rr->rectf);
|
||||
}
|
||||
RE_RenderByteBuffer_data_free(&rr->byte_buffer);
|
||||
RE_RenderBuffer_data_free(&rr->combined_buffer);
|
||||
RE_RenderBuffer_data_free(&rr->z_buffer);
|
||||
|
||||
if (rr->text) {
|
||||
MEM_freeN(rr->text);
|
||||
}
|
||||
|
@ -142,9 +129,10 @@ void render_result_views_shallowcopy(RenderResult *dst, RenderResult *src)
|
|||
BLI_addtail(&dst->views, rv);
|
||||
|
||||
STRNCPY(rv->name, rview->name);
|
||||
rv->rectf = rview->rectf;
|
||||
rv->rectz = rview->rectz;
|
||||
rv->rect32 = rview->rect32;
|
||||
|
||||
rv->combined_buffer = rview->combined_buffer;
|
||||
rv->z_buffer = rview->z_buffer;
|
||||
rv->byte_buffer = rview->byte_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,24 +153,24 @@ void render_result_views_shallowdelete(RenderResult *rr)
|
|||
|
||||
static void render_layer_allocate_pass(RenderResult *rr, RenderPass *rp)
|
||||
{
|
||||
if (rp->rect != nullptr) {
|
||||
if (rp->buffer.data != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t rectsize = size_t(rr->rectx) * rr->recty * rp->channels;
|
||||
rp->rect = MEM_cnew_array<float>(rectsize, rp->name);
|
||||
float *buffer_data = MEM_cnew_array<float>(rectsize, rp->name);
|
||||
|
||||
rp->buffer = RE_RenderBuffer_new(buffer_data);
|
||||
|
||||
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;
|
||||
buffer_data[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;
|
||||
buffer_data[x] = 10e10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -413,6 +401,11 @@ void RE_create_render_pass(RenderResult *rr,
|
|||
}
|
||||
}
|
||||
|
||||
void RE_pass_set_buffer_data(struct RenderPass *pass, float *data)
|
||||
{
|
||||
RE_RenderBuffer_assign_data(&pass->buffer, data);
|
||||
}
|
||||
|
||||
void RE_render_result_full_channel_name(char *fullname,
|
||||
const char *layname,
|
||||
const char *passname,
|
||||
|
@ -515,7 +508,8 @@ static void ml_addpass_cb(void *base,
|
|||
/* channel id chars */
|
||||
STRNCPY(rpass->chan_id, chan_id);
|
||||
|
||||
rpass->rect = rect;
|
||||
RE_pass_set_buffer_data(rpass, rect);
|
||||
|
||||
STRNCPY(rpass->name, name);
|
||||
STRNCPY(rpass->view, view);
|
||||
RE_render_result_full_channel_name(rpass->fullname, nullptr, name, view, rpass->chan_id, -1);
|
||||
|
@ -638,7 +632,7 @@ RenderResult *render_result_new_from_exr(
|
|||
rpass->recty = recty;
|
||||
|
||||
if (rpass->channels >= 3) {
|
||||
IMB_colormanagement_transform(rpass->rect,
|
||||
IMB_colormanagement_transform(rpass->buffer.data,
|
||||
rpass->rectx,
|
||||
rpass->recty,
|
||||
rpass->channels,
|
||||
|
@ -718,7 +712,7 @@ 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->rect == nullptr || rpassp->rect == nullptr) {
|
||||
if (rpass->buffer.data == nullptr || rpassp->buffer.data == nullptr) {
|
||||
continue;
|
||||
}
|
||||
/* Render-result have all passes, render-part only the active view's passes. */
|
||||
|
@ -726,7 +720,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
|
|||
continue;
|
||||
}
|
||||
|
||||
do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
|
||||
do_merge_tile(rr, rrpart, rpass->buffer.data, rpassp->buffer.data, rpass->channels);
|
||||
|
||||
/* manually get next render pass */
|
||||
rpassp = rpassp->next;
|
||||
|
@ -825,7 +819,7 @@ int render_result_exr_file_read_path(RenderResult *rr,
|
|||
RE_render_result_full_channel_name(
|
||||
fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, a);
|
||||
IMB_exr_set_channel(
|
||||
exrhandle, rl->name, fullname, xstride, xstride * rectx, rpass->rect + a);
|
||||
exrhandle, rl->name, fullname, xstride, xstride * rectx, rpass->buffer.data + a);
|
||||
}
|
||||
|
||||
RE_render_result_full_channel_name(
|
||||
|
@ -931,9 +925,9 @@ 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_byte_buffer(ibuf, reinterpret_cast<uint8_t *>(rv->rect32), IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
IMB_assign_float_buffer(ibuf, rv->rectf, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
IMB_assign_float_z_buffer(ibuf, rv->rectz, IB_DO_NOT_TAKE_OWNERSHIP);
|
||||
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);
|
||||
IMB_assign_shared_float_z_buffer(ibuf, rv->z_buffer.data, rv->z_buffer.sharing_info);
|
||||
|
||||
/* float factor for random dither, imbuf takes care of it */
|
||||
ibuf->dither = dither;
|
||||
|
@ -978,27 +972,31 @@ void RE_render_result_rect_from_ibuf(RenderResult *rr, const ImBuf *ibuf, const
|
|||
if (ibuf->float_buffer.data) {
|
||||
rr->have_combined = true;
|
||||
|
||||
if (!rv->rectf) {
|
||||
rv->rectf = MEM_cnew_array<float>(4 * rr->rectx * rr->recty, "render_seq rectf");
|
||||
if (!rv->combined_buffer.data) {
|
||||
float *data = MEM_cnew_array<float>(4 * rr->rectx * rr->recty, "render_seq rectf");
|
||||
RE_RenderBuffer_assign_data(&rv->combined_buffer, data);
|
||||
}
|
||||
|
||||
memcpy(rv->rectf, ibuf->float_buffer.data, sizeof(float[4]) * rr->rectx * rr->recty);
|
||||
memcpy(rv->combined_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 */
|
||||
MEM_SAFE_FREE(rv->rect32);
|
||||
RE_RenderByteBuffer_data_free(&rv->byte_buffer);
|
||||
}
|
||||
else if (ibuf->byte_buffer.data) {
|
||||
rr->have_combined = true;
|
||||
|
||||
if (!rv->rect32) {
|
||||
rv->rect32 = MEM_cnew_array<int>(rr->rectx * rr->recty, "render_seq rect");
|
||||
if (!rv->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);
|
||||
}
|
||||
|
||||
memcpy(rv->rect32, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
|
||||
memcpy(rv->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. */
|
||||
MEM_SAFE_FREE(rv->rectf);
|
||||
RE_RenderBuffer_data_free(&rv->combined_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1006,14 +1004,15 @@ void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
|
|||
{
|
||||
RenderView *rv = RE_RenderViewGetById(rr, view_id);
|
||||
|
||||
if (rv->rectf) {
|
||||
memset(rv->rectf, 0, sizeof(float[4]) * rr->rectx * rr->recty);
|
||||
if (rv->combined_buffer.data) {
|
||||
memset(rv->combined_buffer.data, 0, sizeof(float[4]) * rr->rectx * rr->recty);
|
||||
}
|
||||
else if (rv->rect32) {
|
||||
memset(rv->rect32, 0, 4 * rr->rectx * rr->recty);
|
||||
else if (rv->byte_buffer.data) {
|
||||
memset(rv->byte_buffer.data, 0, 4 * rr->rectx * rr->recty);
|
||||
}
|
||||
else {
|
||||
rv->rect32 = MEM_cnew_array<int>(rr->rectx * rr->recty, "render_seq rect");
|
||||
uint8_t *data = MEM_cnew_array<uint8_t>(rr->rectx * rr->recty, "render_seq rect");
|
||||
RE_RenderByteBuffer_assign_data(&rv->byte_buffer, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1027,12 +1026,18 @@ void render_result_rect_get_pixels(RenderResult *rr,
|
|||
{
|
||||
RenderView *rv = RE_RenderViewGetById(rr, view_id);
|
||||
|
||||
if (rv && rv->rect32) {
|
||||
memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty);
|
||||
if (rv && rv->byte_buffer.data) {
|
||||
memcpy(rect, rv->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
|
||||
}
|
||||
else if (rv && rv->rectf) {
|
||||
IMB_display_buffer_transform_apply(
|
||||
(uchar *)rect, rv->rectf, rr->rectx, rr->recty, 4, view_settings, display_settings, true);
|
||||
else if (rv && rv->combined_buffer.data) {
|
||||
IMB_display_buffer_transform_apply((uchar *)rect,
|
||||
rv->combined_buffer.data,
|
||||
rr->rectx,
|
||||
rr->recty,
|
||||
4,
|
||||
view_settings,
|
||||
display_settings,
|
||||
true);
|
||||
}
|
||||
else {
|
||||
/* else fill with black */
|
||||
|
@ -1053,13 +1058,13 @@ bool RE_HasCombinedLayer(const RenderResult *result)
|
|||
return false;
|
||||
}
|
||||
|
||||
return (rv->rect32 || rv->rectf);
|
||||
return (rv->byte_buffer.data || rv->combined_buffer.data);
|
||||
}
|
||||
|
||||
bool RE_HasFloatPixels(const RenderResult *result)
|
||||
{
|
||||
LISTBASE_FOREACH (const RenderView *, rview, &result->views) {
|
||||
if (rview->rect32 && !rview->rectf) {
|
||||
if (rview->byte_buffer.data && !rview->combined_buffer.data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1099,9 +1104,11 @@ 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->rect != nullptr) {
|
||||
new_rpass->rect = static_cast<float *>(MEM_dupallocN(new_rpass->rect));
|
||||
|
||||
if (new_rpass->buffer.sharing_info != nullptr) {
|
||||
new_rpass->buffer.sharing_info->add_user();
|
||||
}
|
||||
|
||||
return new_rpass;
|
||||
}
|
||||
|
||||
|
@ -1121,15 +1128,22 @@ static RenderLayer *duplicate_render_layer(RenderLayer *rl)
|
|||
static RenderView *duplicate_render_view(RenderView *rview)
|
||||
{
|
||||
RenderView *new_rview = MEM_cnew<RenderView>("new render view", *rview);
|
||||
if (new_rview->rectf != nullptr) {
|
||||
new_rview->rectf = static_cast<float *>(MEM_dupallocN(new_rview->rectf));
|
||||
|
||||
if (rview->combined_buffer.data != nullptr) {
|
||||
RE_RenderBuffer_assign_data(&new_rview->combined_buffer,
|
||||
static_cast<float *>(MEM_dupallocN(rview->combined_buffer.data)));
|
||||
}
|
||||
if (new_rview->rectz != nullptr) {
|
||||
new_rview->rectz = static_cast<float *>(MEM_dupallocN(new_rview->rectz));
|
||||
|
||||
if (rview->z_buffer.data != nullptr) {
|
||||
RE_RenderBuffer_assign_data(&new_rview->z_buffer,
|
||||
static_cast<float *>(MEM_dupallocN(rview->z_buffer.data)));
|
||||
}
|
||||
if (new_rview->rect32 != nullptr) {
|
||||
new_rview->rect32 = static_cast<int *>(MEM_dupallocN(new_rview->rect32));
|
||||
|
||||
if (rview->byte_buffer.data != nullptr) {
|
||||
RE_RenderByteBuffer_assign_data(
|
||||
&new_rview->byte_buffer, static_cast<uint8_t *>(MEM_dupallocN(rview->byte_buffer.data)));
|
||||
}
|
||||
|
||||
return new_rview;
|
||||
}
|
||||
|
||||
|
@ -1147,15 +1161,105 @@ RenderResult *RE_DuplicateRenderResult(RenderResult *rr)
|
|||
RenderView *new_rview = duplicate_render_view(rview);
|
||||
BLI_addtail(&new_rr->views, new_rview);
|
||||
}
|
||||
if (new_rr->rectf != nullptr) {
|
||||
new_rr->rectf = static_cast<float *>(MEM_dupallocN(new_rr->rectf));
|
||||
}
|
||||
if (new_rr->rectz != nullptr) {
|
||||
new_rr->rectz = static_cast<float *>(MEM_dupallocN(new_rr->rectz));
|
||||
}
|
||||
if (new_rr->rect32 != nullptr) {
|
||||
new_rr->rect32 = static_cast<int *>(MEM_dupallocN(new_rr->rect32));
|
||||
}
|
||||
|
||||
RE_RenderBuffer_assign_data(&new_rr->combined_buffer,
|
||||
static_cast<float *>(MEM_dupallocN(rr->combined_buffer.data)));
|
||||
RE_RenderBuffer_assign_data(&new_rr->z_buffer,
|
||||
static_cast<float *>(MEM_dupallocN(rr->z_buffer.data)));
|
||||
|
||||
RE_RenderByteBuffer_assign_data(&new_rr->byte_buffer,
|
||||
static_cast<uint8_t *>(MEM_dupallocN(rr->byte_buffer.data)));
|
||||
|
||||
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)
|
||||
{
|
||||
BufferType buffer;
|
||||
|
||||
buffer.data = data;
|
||||
buffer.sharing_info = blender::implicit_sharing::info_for_mem_free(data);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
blender::implicit_sharing::free_shared_data(&render_buffer->data, &render_buffer->sharing_info);
|
||||
}
|
||||
|
||||
template<class BufferType>
|
||||
static void render_buffer_assign_data(BufferType *render_buffer, decltype(BufferType::data) data)
|
||||
{
|
||||
render_buffer_data_free(render_buffer);
|
||||
|
||||
if (!data) {
|
||||
render_buffer->data = nullptr;
|
||||
render_buffer->sharing_info = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1575,25 +1575,24 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
|
|||
|
||||
RE_AcquireResultImage(re, &rres, view_id);
|
||||
|
||||
if (rres.rectf) {
|
||||
ibufs_arr[view_id] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
|
||||
memcpy(ibufs_arr[view_id]->float_buffer.data,
|
||||
rres.rectf,
|
||||
sizeof(float[4]) * rres.rectx * rres.recty);
|
||||
if (rres.combined_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);
|
||||
|
||||
if (rres.rectz) {
|
||||
addzbuffloatImBuf(ibufs_arr[view_id]);
|
||||
memcpy(ibufs_arr[view_id]->float_z_buffer.data,
|
||||
rres.rectz,
|
||||
sizeof(float) * rres.rectx * rres.recty);
|
||||
if (rres.z_buffer.data) {
|
||||
IMB_assign_shared_float_z_buffer(
|
||||
ibufs_arr[view_id], rres.z_buffer.data, rres.z_buffer.sharing_info);
|
||||
}
|
||||
|
||||
/* float buffers in the sequencer are not linear */
|
||||
seq_imbuf_to_sequencer_space(context->scene, ibufs_arr[view_id], false);
|
||||
}
|
||||
else if (rres.rect32) {
|
||||
else if (rres.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.rect32, 4 * rres.rectx * rres.recty);
|
||||
memcpy(ibufs_arr[view_id]->byte_buffer.data,
|
||||
rres.byte_buffer.data,
|
||||
4 * rres.rectx * rres.recty);
|
||||
}
|
||||
|
||||
if (view_id != context->view_id) {
|
||||
|
|
Loading…
Reference in New Issue
Grammar:
allows to implicitly share
->allows implicitly sharing