diff options
Diffstat (limited to 'source')
51 files changed, 770 insertions, 1019 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index b3ee2f411d7..1f25106404a 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 24 +#define BLENDER_FILE_SUBVERSION 25 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index b489675cd74..434a2296d95 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -183,7 +183,6 @@ static ViewLayer *view_layer_add(const char *name) view_layer->passflag = SCE_PASS_COMBINED; view_layer->pass_alpha_threshold = 0.5f; view_layer->cryptomatte_levels = 6; - view_layer->cryptomatte_flag = VIEW_LAYER_CRYPTOMATTE_ACCURATE; BKE_freestyle_config_init(&view_layer->freestyle_config); return view_layer; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index fa15e541e43..54d1efab7dd 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -651,13 +651,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) mat->line_col[3] = mat->alpha; } } - - if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) { - Scene *scene; - for (scene = bmain->scenes.first; scene; scene = scene->id.next) { - scene->r.preview_start_resolution = 64; - } - } } if (!MAIN_VERSION_ATLEAST(bmain, 271, 3)) { @@ -698,15 +691,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - if (!MAIN_VERSION_ATLEAST(bmain, 272, 0)) { - if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) { - Scene *scene; - for (scene = bmain->scenes.first; scene; scene = scene->id.next) { - scene->r.preview_start_resolution = 64; - } - } - } - if (!MAIN_VERSION_ATLEAST(bmain, 272, 1)) { Brush *br; for (br = bmain->brushes.first; br; br = br->id.next) { diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 9f2c090c242..69b67460a5d 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -3718,7 +3718,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) STRNCPY(node->idname, "ShaderNodeOutputLight"); } if (node->type == SH_NODE_BSDF_PRINCIPLED && node->custom2 == 0) { - node->custom2 = SHD_SUBSURFACE_BURLEY; + node->custom2 = SHD_SUBSURFACE_DIFFUSION; } } } diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index bafba486c88..be8c4b735be 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1461,7 +1461,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { view_layer->cryptomatte_levels = 6; - view_layer->cryptomatte_flag = VIEW_LAYER_CRYPTOMATTE_ACCURATE; } } } diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 1a19bbbee5c..4dc6a0ecea6 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -784,6 +784,20 @@ static bool seq_transform_origin_set(Sequence *seq, void *UNUSED(user_data)) return true; } +static void do_version_subsurface_methods(bNode *node) +{ + if (node->type == SH_NODE_SUBSURFACE_SCATTERING) { + if (node->custom1 != SHD_SUBSURFACE_RANDOM_WALK) { + node->custom1 = SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS; + } + } + else if (node->type == SH_NODE_BSDF_PRINCIPLED) { + if (node->custom2 != SHD_SUBSURFACE_RANDOM_WALK) { + node->custom2 = SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS; + } + } +} + /* NOLINTNEXTLINE: readability-function-size */ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) { @@ -1336,6 +1350,25 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 300, 25)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + do_version_subsurface_methods(node); + } + } + } + FOREACH_NODETREE_END; + + enum { + R_EXR_TILE_FILE = (1 << 10), + R_FULL_SAMPLE = (1 << 15), + }; + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + scene->r.scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE); + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index 90e6b43f02e..da57f27af4e 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -182,8 +182,8 @@ static void displacement_principled_nodes(bNode *node) } } else if (node->type == SH_NODE_BSDF_PRINCIPLED) { - if (node->custom2 != SHD_SUBSURFACE_RANDOM_WALK) { - node->custom2 = SHD_SUBSURFACE_BURLEY; + if (node->custom2 != SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS) { + node->custom2 = SHD_SUBSURFACE_DIFFUSION; } } } @@ -1373,6 +1373,11 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm void do_versions_after_linking_cycles(Main *bmain) { + const int DENOISER_AUTO = 0; + const int DENOISER_NLM = 1; + const int DENOISER_OPTIX = 2; + const int DENOISER_OPENIMAGEDENOISE = 4; + if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) { /* Shader node tree changes. After lib linking so we have all the typeinfo * pointers and updated sockets and we can use the high level node API to @@ -1578,10 +1583,6 @@ void do_versions_after_linking_cycles(Main *bmain) } if (cscene) { - const int DENOISER_AUTO = 0; - const int DENOISER_NLM = 1; - const int DENOISER_OPTIX = 2; - /* Enable denoiser if it was enabled for one view layer before. */ cycles_property_int_set(cscene, "denoiser", (use_optix) ? DENOISER_OPTIX : DENOISER_NLM); cycles_property_boolean_set(cscene, "use_denoising", use_denoising); @@ -1637,4 +1638,17 @@ void do_versions_after_linking_cycles(Main *bmain) object->visibility_flag |= flag; } } + + if (!MAIN_VERSION_ATLEAST(bmain, 300, 25)) { + /* Removal of NLM denoiser. */ + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + IDProperty *cscene = cycles_properties_from_ID(&scene->id); + + if (cscene) { + if (cycles_property_int(cscene, "denoiser", DENOISER_NLM) == DENOISER_NLM) { + cycles_property_int_set(cscene, "denoiser", DENOISER_OPENIMAGEDENOISE); + } + } + } + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f2d5896be03..152ef79a38f 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -54,6 +54,7 @@ #include "BKE_curveprofile.h" #include "BKE_customdata.h" #include "BKE_gpencil.h" +#include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -356,6 +357,12 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) if (ts->custom_bevel_profile_preset == NULL) { ts->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE); } + + /* Clear ID properties so Cycles gets defaults. */ + IDProperty *idprop = IDP_GetProperties(&scene->id, false); + if (idprop) { + IDP_ClearProperty(idprop); + } } /** @@ -582,6 +589,10 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness"); bNodeSocketValueFloat *roughness_data = roughness_socket->default_value; roughness_data->value = 0.4f; + node->custom2 = SHD_SUBSURFACE_RANDOM_WALK; + } + else if (node->type == SH_NODE_SUBSURFACE_SCATTERING) { + node->custom1 = SHD_SUBSURFACE_RANDOM_WALK; } } } diff --git a/source/blender/compositor/nodes/COM_IDMaskNode.cc b/source/blender/compositor/nodes/COM_IDMaskNode.cc index b51e79f2dea..761cb8b98cf 100644 --- a/source/blender/compositor/nodes/COM_IDMaskNode.cc +++ b/source/blender/compositor/nodes/COM_IDMaskNode.cc @@ -28,7 +28,7 @@ IDMaskNode::IDMaskNode(bNode *editorNode) : Node(editorNode) /* pass */ } void IDMaskNode::convertToOperations(NodeConverter &converter, - const CompositorContext &context) const + const CompositorContext & /*context*/) const { bNode *bnode = this->getbNode(); @@ -38,7 +38,7 @@ void IDMaskNode::convertToOperations(NodeConverter &converter, converter.addOperation(operation); converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0)); - if (bnode->custom2 == 0 || context.getRenderData()->scemode & R_FULL_SAMPLE) { + if (bnode->custom2 == 0) { converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0)); } else { diff --git a/source/blender/compositor/nodes/COM_ZCombineNode.cc b/source/blender/compositor/nodes/COM_ZCombineNode.cc index ddf66740578..e29748dc317 100644 --- a/source/blender/compositor/nodes/COM_ZCombineNode.cc +++ b/source/blender/compositor/nodes/COM_ZCombineNode.cc @@ -31,9 +31,9 @@ namespace blender::compositor { void ZCombineNode::convertToOperations(NodeConverter &converter, - const CompositorContext &context) const + const CompositorContext & /*context*/) const { - if ((context.getRenderData()->scemode & R_FULL_SAMPLE) || this->getbNode()->custom2) { + if (this->getbNode()->custom2) { ZCombineOperation *operation = nullptr; if (this->getbNode()->custom1) { operation = new ZCombineAlphaOperation(); diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index a125a13eaf9..2e25211ea62 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -176,6 +176,9 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat); struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id); void DRW_drawdata_free(struct ID *id); +bool DRW_opengl_context_release(void); +void DRW_opengl_context_activate(bool test); + #ifdef __cplusplus } #endif diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index 76a1b561972..49780abc6f4 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -139,8 +139,6 @@ void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata) g_data->cryptomatte_session = session; g_data->render_passes |= EEVEE_RENDER_PASS_CRYPTOMATTE | EEVEE_RENDER_PASS_VOLUME_LIGHT; - g_data->cryptomatte_accurate_mode = (view_layer->cryptomatte_flag & - VIEW_LAYER_CRYPTOMATTE_ACCURATE) != 0; } } @@ -405,7 +403,6 @@ void EEVEE_cryptomatte_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EE { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PassList *psl = vedata->psl; const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -413,10 +410,9 @@ void EEVEE_cryptomatte_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EE const int cryptomatte_levels = view_layer->cryptomatte_levels; const int current_sample = effects->taa_current_sample; - /* In accurate mode all render samples are evaluated. In inaccurate mode this is limited to the - * number of cryptomatte levels. This will reduce the overhead of downloading the GPU buffer and - * integrating it into the accum buffer. */ - if (g_data->cryptomatte_accurate_mode || current_sample < cryptomatte_levels) { + /* Render samples used by cryptomatte are limited to the number of cryptomatte levels. This will + * reduce the overhead of downloading the GPU buffer and integrating it into the accum buffer. */ + if (current_sample < cryptomatte_levels) { static float clear_color[4] = {0.0}; GPU_framebuffer_bind(fbl->cryptomatte_fb); GPU_framebuffer_clear_color(fbl->cryptomatte_fb, clear_color); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 6a66e8b1a58..f8e1cc9c923 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -648,6 +648,8 @@ RenderEngineType DRW_engine_viewport_eevee_type = { NULL, NULL, NULL, + NULL, + NULL, &EEVEE_render_update_passes, &draw_engine_eevee_type, {NULL, NULL, NULL}, diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index f51b4fa0127..eae5d161cc3 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -1042,7 +1042,6 @@ typedef struct EEVEE_PrivateData { int aov_hash; int num_aovs_used; struct CryptomatteSession *cryptomatte_session; - bool cryptomatte_accurate_mode; EEVEE_CryptomatteSample *cryptomatte_accum_buffer; float *cryptomatte_download_buffer; diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 89ee3f1b293..cc548a53a8e 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -32,13 +32,19 @@ #include "BKE_object.h" #include "BKE_particle.h" +#include "ED_image.h" #include "ED_screen.h" +#include "GPU_batch.h" +#include "GPU_debug.h" #include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_state.h" #include "GPU_viewport.h" +#include "RE_engine.h" +#include "RE_pipeline.h" + #include "external_engine.h" /* own include */ /* Shaders */ @@ -137,6 +143,22 @@ static void external_engine_init(void *vedata) } } +/* Add shading group call which will take care of writing to the depth buffer, so that the + * alpha-under overlay will happen for the render buffer. */ +static void external_cache_image_add(DRWShadingGroup *grp) +{ + float obmat[4][4]; + unit_m4(obmat); + scale_m4_fl(obmat, 0.5f); + + /* NOTE: Use the same Z-depth value as in the regular image drawing engine. */ + translate_m4(obmat, 1.0f, 1.0f, 0.75f); + + GPUBatch *geom = DRW_cache_quad_get(); + + DRW_shgroup_call_obmat(grp, geom, obmat); +} + static void external_cache_init(void *vedata) { EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl; @@ -162,14 +184,33 @@ static void external_cache_init(void *vedata) stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); } - /* Do not draw depth pass when overlays are turned off. */ - stl->g_data->need_depth = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + if (v3d != NULL) { + /* Do not draw depth pass when overlays are turned off. */ + stl->g_data->need_depth = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + } + else if (draw_ctx->space_data != NULL) { + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + external_cache_image_add(stl->g_data->depth_shgrp); + + stl->g_data->need_depth = true; + stl->g_data->update_depth = true; + } + } } static void external_cache_populate(void *vedata, Object *ob) { + const DRWContextState *draw_ctx = DRW_context_state_get(); EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; + if (draw_ctx->space_data != NULL) { + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + return; + } + } + if (!(DRW_object_is_renderable(ob) && DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { return; @@ -210,13 +251,11 @@ static void external_cache_finish(void *UNUSED(vedata)) { } -static void external_draw_scene_do(void *vedata) +static void external_draw_scene_do_v3d(void *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; RegionView3D *rv3d = draw_ctx->rv3d; ARegion *region = draw_ctx->region; - const RenderEngineType *type; DRW_state_reset_ex(DRW_STATE_DEFAULT & ~DRW_STATE_DEPTH_LESS_EQUAL); @@ -229,8 +268,6 @@ static void external_draw_scene_do(void *vedata) } RenderEngine *engine = RE_engine_create(engine_type); - engine->tile_x = scene->r.tilex; - engine->tile_y = scene->r.tiley; engine_type->view_update(engine, draw_ctx->evil_C, draw_ctx->depsgraph); rv3d->render_engine = engine; } @@ -241,7 +278,7 @@ static void external_draw_scene_do(void *vedata) ED_region_pixelspace(region); /* Render result draw. */ - type = rv3d->render_engine->type; + const RenderEngineType *type = rv3d->render_engine->type; type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph); GPU_bgl_end(); @@ -259,6 +296,116 @@ static void external_draw_scene_do(void *vedata) } } +/* Configure current matrix stack so that the external engine can use the same drawing code for + * both viewport and image editor drawing. + * + * The engine draws result in the pixel space, and is applying render offset. For image editor we + * need to switch from normalized space to pixel space, and "un-apply" offset. */ +static void external_image_space_matrix_set(const RenderEngine *engine) +{ + BLI_assert(engine != NULL); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const DRWView *view = DRW_view_get_active(); + struct SpaceImage *space_image = (struct SpaceImage *)draw_ctx->space_data; + + /* Apply current view as transformation matrix. + * This will configure drawing for normalized space with current zoom and pan applied. */ + + float view_matrix[4][4]; + DRW_view_viewmat_get(view, view_matrix, false); + + float projection_matrix[4][4]; + DRW_view_winmat_get(view, projection_matrix, false); + + GPU_matrix_projection_set(projection_matrix); + GPU_matrix_set(view_matrix); + + /* Switch from normalized space to pixel space. */ + { + int width, height; + ED_space_image_get_size(space_image, &width, &height); + + const float width_inv = width ? 1.0f / width : 0.0f; + const float height_inv = height ? 1.0f / height : 0.0f; + GPU_matrix_scale_2f(width_inv, height_inv); + } + + /* Un-apply render offset. */ + { + Render *render = engine->re; + rctf view_rect; + rcti render_rect; + RE_GetViewPlane(render, &view_rect, &render_rect); + + GPU_matrix_translate_2f(-render_rect.xmin, -render_rect.ymin); + } +} + +static void external_draw_scene_do_image(void *UNUSED(vedata)) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + Render *re = RE_GetSceneRender(scene); + RenderEngine *engine = RE_engine_get(re); + + /* Is tested before enabling the drawing engine. */ + BLI_assert(re != NULL); + BLI_assert(engine != NULL); + + const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + /* Clear the depth buffer to the value used by the background overlay so that the overlay is not + * happening outside of the drawn image. + * + * NOTE: The external engine only draws color. The depth is taken care of using the depth pass + * which initialized the depth to the values expected by the background overlay. */ + GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); + + GPU_matrix_push_projection(); + GPU_matrix_push(); + + external_image_space_matrix_set(engine); + + GPU_debug_group_begin("External Engine"); + + const RenderEngineType *engine_type = engine->type; + BLI_assert(engine_type != NULL); + BLI_assert(engine_type->draw != NULL); + + engine_type->draw(engine, draw_ctx->evil_C, draw_ctx->depsgraph); + + GPU_debug_group_end(); + + GPU_matrix_pop(); + GPU_matrix_pop_projection(); + + DRW_state_reset(); + GPU_bgl_end(); + + RE_engine_draw_release(re); +} + +static void external_draw_scene_do(void *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (draw_ctx->v3d != NULL) { + external_draw_scene_do_v3d(vedata); + return; + } + + if (draw_ctx->space_data == NULL) { + return; + } + + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + external_draw_scene_do_image(vedata); + return; + } +} + static void external_draw_scene(void *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -297,7 +444,7 @@ static void external_engine_free(void) static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data); -static DrawEngineType draw_engine_external_type = { +DrawEngineType draw_engine_external_type = { NULL, NULL, N_("External"), @@ -330,8 +477,45 @@ RenderEngineType DRW_engine_viewport_external_type = { NULL, NULL, NULL, + NULL, + NULL, &draw_engine_external_type, {NULL, NULL, NULL}, }; +bool DRW_engine_external_acquire_for_image_editor(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const SpaceLink *space_data = draw_ctx->space_data; + Scene *scene = draw_ctx->scene; + + if (space_data == NULL) { + return false; + } + + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type != SPACE_IMAGE) { + return false; + } + + struct SpaceImage *space_image = (struct SpaceImage *)space_data; + const Image *image = ED_space_image(space_image); + if (image == NULL || image->type != IMA_TYPE_R_RESULT) { + return false; + } + + if (image->render_slot != image->last_render_slot) { + return false; + } + + /* Render is allocated on main thread, so it is safe to access it from here. */ + Render *re = RE_GetSceneRender(scene); + + if (re == NULL) { + return false; + } + + return RE_engine_draw_acquire(re); +} + #undef EXTERNAL_ENGINE diff --git a/source/blender/draw/engines/external/external_engine.h b/source/blender/draw/engines/external/external_engine.h index c645fb99e0e..14ec4e2d3c5 100644 --- a/source/blender/draw/engines/external/external_engine.h +++ b/source/blender/draw/engines/external/external_engine.h @@ -22,4 +22,12 @@ #pragma once +extern DrawEngineType draw_engine_external_type; extern RenderEngineType DRW_engine_viewport_external_type; + +/* Check whether an external engine is to be used to draw content of an image editor. + * If the drawing is possible, the render engine is "acquired" so that it is not freed by the + * render engine for until drawing is finished. + * + * NOTE: Released by the draw engine when it is done drawing. */ +bool DRW_engine_external_acquire_for_image_editor(void); diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index 96ab8a28e09..20edd78597b 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -388,6 +388,8 @@ RenderEngineType DRW_engine_viewport_select_type = { NULL, NULL, NULL, + NULL, + NULL, &draw_engine_select_type, {NULL, NULL, NULL}, }; diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index f09c019ef8d..635aa7cef25 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -651,6 +651,8 @@ RenderEngineType DRW_engine_viewport_workbench_type = { NULL, NULL, NULL, + NULL, + NULL, &workbench_render_update_passes, &draw_engine_workbench, {NULL, NULL, NULL}, diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 660a4adaf51..fb8b8536897 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -623,6 +623,7 @@ const DRWView *DRW_view_default_get(void); void DRW_view_default_set(DRWView *view); void DRW_view_reset(void); void DRW_view_set_active(DRWView *view); +const DRWView *DRW_view_get_active(void); void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len); void DRW_view_camtexco_set(DRWView *view, float texco[4]); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 47adc0acc60..e65fdce5f2e 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1197,6 +1197,18 @@ static void drw_engines_enable_basic(void) use_drw_engine(&draw_engine_basic_type); } +static void drw_engine_enable_image_editor(void) +{ + if (DRW_engine_external_acquire_for_image_editor()) { + use_drw_engine(&draw_engine_external_type); + } + else { + use_drw_engine(&draw_engine_image_type); + } + + use_drw_engine(&draw_engine_overlay_type); +} + static void drw_engines_enable_editors(void) { SpaceLink *space_data = DST.draw_ctx.space_data; @@ -1205,8 +1217,7 @@ static void drw_engines_enable_editors(void) } if (space_data->spacetype == SPACE_IMAGE) { - use_drw_engine(&draw_engine_image_type); - use_drw_engine(&draw_engine_overlay_type); + drw_engine_enable_image_editor(); } else if (space_data->spacetype == SPACE_NODE) { /* Only enable when drawing the space image backdrop. */ @@ -3188,3 +3199,66 @@ void DRW_draw_state_init_gtests(eGPUShaderConfig sh_cfg) #endif /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw manager context release/activation + * + * These functions are used in cases when an OpenGL context creation is needed during the draw. + * This happens, for example, when an external engine needs to create its own OpenGL context from + * the engine initialization. + * + * Example of context creation: + * + * const bool drw_state = DRW_opengl_context_release(); + * gl_context = WM_opengl_context_create(); + * DRW_opengl_context_activate(drw_state); + * + * Example of context destruction: + * + * const bool drw_state = DRW_opengl_context_release(); + * WM_opengl_context_activate(gl_context); + * WM_opengl_context_dispose(gl_context); + * DRW_opengl_context_activate(drw_state); + * + * + * NOTE: Will only perform context modification when on main thread. This way these functions can + * be used in an engine without check on whether it is a draw manager which manages OpenGL context + * on the current thread. The downside of this is that if the engine performs OpenGL creation from + * a non-main thread, that thread is supposed to not have OpenGL context ever bound by Blender. + * + * \{ */ + +bool DRW_opengl_context_release(void) +{ + if (!BLI_thread_is_main()) { + return false; + } + + if (GPU_context_active_get() != DST.gpu_context) { + /* Context release is requested from the outside of the draw manager main draw loop, indicate + * this to the `DRW_opengl_context_activate()` so that it restores drawable of the window. */ + return false; + } + + GPU_context_active_set(NULL); + WM_opengl_context_release(DST.gl_context); + + return true; +} + +void DRW_opengl_context_activate(bool drw_state) +{ + if (!BLI_thread_is_main()) { + return; + } + + if (drw_state) { + WM_opengl_context_activate(DST.gl_context); + GPU_context_active_set(DST.gpu_context); + } + else { + wm_window_reset_drawable(); + } +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 22356a3c57b..aa01ca7a262 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -367,6 +367,11 @@ void DRW_view_set_active(DRWView *view) DST.view_active = (view) ? view : DST.view_default; } +const DRWView *DRW_view_get_active(void) +{ + return DST.view_active; +} + /* Return True if the given BoundSphere intersect the current view frustum */ static bool draw_culling_sphere_test(const BoundSphere *frustum_bsphere, const float (*frustum_planes)[4], diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 0a2df655395..26f5b21a311 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -412,6 +412,7 @@ static bool is_noncolor_pass(eScenePassType pass_type) { return ELEM(pass_type, SCE_PASS_Z, + SCE_PASS_POSITION, SCE_PASS_NORMAL, SCE_PASS_VECTOR, SCE_PASS_INDEXOB, @@ -554,19 +555,10 @@ static bool bake_pass_filter_check(eScenePassType pass_type, return true; } - if ((pass_filter & R_BAKE_PASS_FILTER_AO) != 0) { - BKE_report( - reports, - RPT_ERROR, - "Combined bake pass Ambient Occlusion contribution requires an enabled light pass " - "(bake the Ambient Occlusion pass type instead)"); - } - else { - BKE_report(reports, - RPT_ERROR, - "Combined bake pass requires Emit, or a light pass with " - "Direct or Indirect contributions enabled"); - } + BKE_report(reports, + RPT_ERROR, + "Combined bake pass requires Emit, or a light pass with " + "Direct or Indirect contributions enabled"); return false; } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 95351de45f0..81aecfdf788 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -479,15 +479,6 @@ static Scene *preview_prepare_scene( BKE_color_managed_view_settings_free(&sce->view_settings); BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings); - /* prevent overhead for small renders and icons (32) */ - if (id && sp->sizex < 40) { - sce->r.tilex = sce->r.tiley = 64; - } - else { - sce->r.tilex = sce->r.xsch / 4; - sce->r.tiley = sce->r.ysch / 4; - } - if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) { sce->r.alphamode = R_ALPHAPREMUL; } diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 937a10f26b1..0a82c237256 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -94,17 +94,15 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) freestyle_scene = BKE_scene_add(freestyle_bmain, name); freestyle_scene->r.cfra = old_scene->r.cfra; freestyle_scene->r.mode = old_scene->r.mode & ~(R_EDGE_FRS | R_BORDER); - freestyle_scene->r.xsch = re->rectx; // old_scene->r.xsch - freestyle_scene->r.ysch = re->recty; // old_scene->r.ysch - freestyle_scene->r.xasp = 1.0f; // old_scene->r.xasp; - freestyle_scene->r.yasp = 1.0f; // old_scene->r.yasp; - freestyle_scene->r.tilex = old_scene->r.tilex; - freestyle_scene->r.tiley = old_scene->r.tiley; + freestyle_scene->r.xsch = re->rectx; // old_scene->r.xsch + freestyle_scene->r.ysch = re->recty; // old_scene->r.ysch + freestyle_scene->r.xasp = 1.0f; // old_scene->r.xasp; + freestyle_scene->r.yasp = 1.0f; // old_scene->r.yasp; freestyle_scene->r.size = 100; // old_scene->r.size freestyle_scene->r.color_mgt_flag = 0; // old_scene->r.color_mgt_flag; freestyle_scene->r.scemode = (old_scene->r.scemode & ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE | R_MULTIVIEW)) & - (re->r.scemode | ~R_FULL_SAMPLE); + (re->r.scemode); freestyle_scene->r.flag = old_scene->r.flag; freestyle_scene->r.threads = old_scene->r.threads; freestyle_scene->r.border.xmin = old_scene->r.border.xmin; diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 312da491a36..e64521768f9 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -175,10 +175,7 @@ GPUNodeLink *GPU_uniformbuf_link_out(struct GPUMaterial *mat, void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link, int hash); -void GPU_material_sss_profile_create(GPUMaterial *material, - float radii[3], - const short *falloff_type, - const float *sharpness); +void GPU_material_sss_profile_create(GPUMaterial *material, float radii[3]); struct GPUUniformBuf *GPU_material_sss_profile_get(GPUMaterial *material, int sample_len, struct GPUTexture **tex_profile); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 56e72fbeca9..6872a08e854 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -96,8 +96,6 @@ struct GPUMaterial { float sss_enabled; float sss_radii[3]; int sss_samples; - short int sss_falloff; - float sss_sharpness; bool sss_dirty; GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */ @@ -266,18 +264,6 @@ static void sss_calculate_offsets(GPUSssKernelData *kd, int count, float exponen } } -#define GAUSS_TRUNCATE 12.46f -static float gaussian_profile(float r, float radius) -{ - const float v = radius * radius * (0.25f * 0.25f); - const float Rm = sqrtf(v * GAUSS_TRUNCATE); - - if (r >= Rm) { - return 0.0f; - } - return expf(-r * r / (2.0f * v)) / (2.0f * M_PI * v); -} - #define BURLEY_TRUNCATE 16.0f #define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE) static float burley_profile(float r, float d) @@ -287,45 +273,15 @@ static float burley_profile(float r, float d) return (exp_r_d + exp_r_3_d) / (4.0f * d); } -static float cubic_profile(float r, float radius, float sharpness) -{ - float Rm = radius * (1.0f + sharpness); - - if (r >= Rm) { - return 0.0f; - } - /* custom variation with extra sharpness, to match the previous code */ - const float y = 1.0f / (1.0f + sharpness); - float Rmy, ry, ryinv; - - Rmy = powf(Rm, y); - ry = powf(r, y); - ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f; - - const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy; - const float f = Rmy - ry; - const float num = f * (f * f) * (y * ryinv); - - return (10.0f * num) / (Rmy5 * M_PI); -} - -static float eval_profile(float r, short falloff_type, float sharpness, float param) +static float eval_profile(float r, float param) { r = fabsf(r); - - if (ELEM(falloff_type, SHD_SUBSURFACE_BURLEY, SHD_SUBSURFACE_RANDOM_WALK)) { - return burley_profile(r, param) / BURLEY_TRUNCATE_CDF; - } - if (falloff_type == SHD_SUBSURFACE_CUBIC) { - return cubic_profile(r, param, sharpness); - } - - return gaussian_profile(r, param); + return burley_profile(r, param) / BURLEY_TRUNCATE_CDF; } /* Resolution for each sample of the precomputed kernel profile */ #define INTEGRAL_RESOLUTION 32 -static float eval_integral(float x0, float x1, short falloff_type, float sharpness, float param) +static float eval_integral(float x0, float x1, float param) { const float range = x1 - x0; const float step = range / INTEGRAL_RESOLUTION; @@ -333,7 +289,7 @@ static float eval_integral(float x0, float x1, short falloff_type, float sharpne for (int i = 0; i < INTEGRAL_RESOLUTION; i++) { float x = x0 + range * ((float)i + 0.5f) / (float)INTEGRAL_RESOLUTION; - float y = eval_profile(x, falloff_type, sharpness, param); + float y = eval_profile(x, param); integral += y * step; } @@ -341,8 +297,7 @@ static float eval_integral(float x0, float x1, short falloff_type, float sharpne } #undef INTEGRAL_RESOLUTION -static void compute_sss_kernel( - GPUSssKernelData *kd, const float radii[3], int sample_len, int falloff_type, float sharpness) +static void compute_sss_kernel(GPUSssKernelData *kd, const float radii[3], int sample_len) { float rad[3]; /* Minimum radius */ @@ -353,27 +308,15 @@ static void compute_sss_kernel( /* Christensen-Burley fitting */ float l[3], d[3]; - if (ELEM(falloff_type, SHD_SUBSURFACE_BURLEY, SHD_SUBSURFACE_RANDOM_WALK)) { - mul_v3_v3fl(l, rad, 0.25f * M_1_PI); - const float A = 1.0f; - const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f); - /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */ - mul_v3_v3fl(d, l, 0.6f / s); - mul_v3_v3fl(rad, d, BURLEY_TRUNCATE); - kd->max_radius = MAX3(rad[0], rad[1], rad[2]); - - copy_v3_v3(kd->param, d); - } - else if (falloff_type == SHD_SUBSURFACE_CUBIC) { - copy_v3_v3(kd->param, rad); - mul_v3_fl(rad, 1.0f + sharpness); - kd->max_radius = MAX3(rad[0], rad[1], rad[2]); - } - else { - kd->max_radius = MAX3(rad[0], rad[1], rad[2]); + mul_v3_v3fl(l, rad, 0.25f * M_1_PI); + const float A = 1.0f; + const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f); + /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */ + mul_v3_v3fl(d, l, 0.6f / s); + mul_v3_v3fl(rad, d, BURLEY_TRUNCATE); + kd->max_radius = MAX3(rad[0], rad[1], rad[2]); - copy_v3_v3(kd->param, rad); - } + copy_v3_v3(kd->param, d); /* Compute samples locations on the 1d kernel [-1..1] */ sss_calculate_offsets(kd, sample_len, SSS_EXPONENT); @@ -403,9 +346,9 @@ static void compute_sss_kernel( x0 *= kd->max_radius; x1 *= kd->max_radius; - kd->kernel[i][0] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[0]); - kd->kernel[i][1] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[1]); - kd->kernel[i][2] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[2]); + kd->kernel[i][0] = eval_integral(x0, x1, kd->param[0]); + kd->kernel[i][1] = eval_integral(x0, x1, kd->param[1]); + kd->kernel[i][2] = eval_integral(x0, x1, kd->param[2]); sum[0] += kd->kernel[i][0]; sum[1] += kd->kernel[i][1]; @@ -439,8 +382,6 @@ static void compute_sss_kernel( #define INTEGRAL_RESOLUTION 512 static void compute_sss_translucence_kernel(const GPUSssKernelData *kd, int resolution, - short falloff_type, - float sharpness, float **output) { float(*texels)[4]; @@ -463,9 +404,9 @@ static void compute_sss_translucence_kernel(const GPUSssKernelData *kd, float dist = hypotf(r + r_step * 0.5f, d); float profile[3]; - profile[0] = eval_profile(dist, falloff_type, sharpness, kd->param[0]); - profile[1] = eval_profile(dist, falloff_type, sharpness, kd->param[1]); - profile[2] = eval_profile(dist, falloff_type, sharpness, kd->param[2]); + profile[0] = eval_profile(dist, kd->param[0]); + profile[1] = eval_profile(dist, kd->param[1]); + profile[2] = eval_profile(dist, kd->param[2]); /* Since the profile and configuration are radially symmetrical we * can just evaluate it once and weight it accordingly */ @@ -499,14 +440,9 @@ static void compute_sss_translucence_kernel(const GPUSssKernelData *kd, } #undef INTEGRAL_RESOLUTION -void GPU_material_sss_profile_create(GPUMaterial *material, - float radii[3], - const short *falloff_type, - const float *sharpness) +void GPU_material_sss_profile_create(GPUMaterial *material, float radii[3]) { copy_v3_v3(material->sss_radii, radii); - material->sss_falloff = (falloff_type) ? *falloff_type : 0.0; - material->sss_sharpness = (sharpness) ? *sharpness : 0.0; material->sss_dirty = true; material->sss_enabled = true; @@ -527,20 +463,14 @@ struct GPUUniformBuf *GPU_material_sss_profile_get(GPUMaterial *material, if (material->sss_dirty || (material->sss_samples != sample_len)) { GPUSssKernelData kd; - float sharpness = material->sss_sharpness; - - /* XXX Black magic but it seems to fit. Maybe because we integrate -1..1 */ - sharpness *= 0.5f; - - compute_sss_kernel(&kd, material->sss_radii, sample_len, material->sss_falloff, sharpness); + compute_sss_kernel(&kd, material->sss_radii, sample_len); /* Update / Create UBO */ GPU_uniformbuf_update(material->sss_profile, &kd); /* Update / Create Tex */ float *translucence_profile; - compute_sss_translucence_kernel( - &kd, 64, material->sss_falloff, sharpness, &translucence_profile); + compute_sss_translucence_kernel(&kd, 64, &translucence_profile); if (material->sss_tex_profile != NULL) { GPU_texture_free(material->sss_tex_profile); diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h index 782d89d6f2a..d3b12d3a2b7 100644 --- a/source/blender/gpu/intern/gpu_material_library.h +++ b/source/blender/gpu/intern/gpu_material_library.h @@ -27,7 +27,7 @@ #include "GPU_material.h" #define MAX_FUNCTION_NAME 64 -#define MAX_PARAMETER 32 +#define MAX_PARAMETER 36 struct GSet; diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index d77259638fd..bba84c2be52 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -19,6 +19,8 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, + float subsurface_ior, + float subsurface_anisotropy, float metallic, float specular, float specular_tint, @@ -201,6 +203,6 @@ void node_bsdf_principled(vec4 base_color, #else /* clang-format off */ /* Stub principled because it is not compatible with volumetrics. */ -# define node_bsdf_principled(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, cc, dd, result) (result = CLOSURE_DEFAULT) +# define node_bsdf_principled(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, cc, dd, ee, ff, result) (result = CLOSURE_DEFAULT) /* clang-format on */ #endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl index 5129bf71903..d0c159cdf37 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl @@ -5,8 +5,8 @@ CLOSURE_EVAL_FUNCTION_DECLARE_1(node_subsurface_scattering, Diffuse) void node_subsurface_scattering(vec4 color, float scale, vec3 radius, - float sharpen, - float texture_blur, + float ior, + float anisotropy, vec3 N, float sss_id, out Closure result) @@ -20,15 +20,7 @@ void node_subsurface_scattering(vec4 color, result = CLOSURE_DEFAULT; - /* Not perfect for texture_blur values between 0.0 and 1.0. - * Interpolate between separated color and color applied on irradiance. */ - float one_minus_texture_blur = 1.0 - texture_blur; - vec3 sss_albedo = color.rgb * one_minus_texture_blur + texture_blur; - vec3 radiance_tint = color.rgb * texture_blur + one_minus_texture_blur; - /* Consider output radiance as irradiance. */ - out_Diffuse_0.radiance *= radiance_tint; - - closure_load_sss_data(scale, out_Diffuse_0.radiance, sss_albedo, int(sss_id), result); + closure_load_sss_data(scale, out_Diffuse_0.radiance, color.rgb, int(sss_id), result); /* TODO(fclem) Try to not use this. */ closure_load_ssr_data(vec3(0.0), 0.0, in_Diffuse_0.N, -1.0, result); diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 63e4597150c..520f989452c 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -68,7 +68,7 @@ typedef enum eViewLayerCryptomatteFlags { VIEW_LAYER_CRYPTOMATTE_OBJECT = (1 << 0), VIEW_LAYER_CRYPTOMATTE_MATERIAL = (1 << 1), VIEW_LAYER_CRYPTOMATTE_ASSET = (1 << 2), - VIEW_LAYER_CRYPTOMATTE_ACCURATE = (1 << 3), + /* VIEW_LAYER_CRYPTOMATTE_ACCURATE = (1 << 3), */ /* DEPRECATED */ } eViewLayerCryptomatteFlags; #define VIEW_LAYER_CRYPTOMATTE_ALL \ (VIEW_LAYER_CRYPTOMATTE_OBJECT | VIEW_LAYER_CRYPTOMATTE_MATERIAL | VIEW_LAYER_CRYPTOMATTE_ASSET) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 49083542fd7..cf159a1e28d 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1032,6 +1032,11 @@ typedef struct NodeShaderTexPointDensity { char _pad2[4]; } NodeShaderTexPointDensity; +typedef struct NodeShaderPrincipled { + char use_subsurface_auto_radius; + char _pad[3]; +} NodeShaderPrincipled; + /* TEX_output */ typedef struct TexNodeOutput { char name[64]; @@ -1803,11 +1808,12 @@ enum { enum { #ifdef DNA_DEPRECATED_ALLOW SHD_SUBSURFACE_COMPATIBLE = 0, /* Deprecated */ -#endif SHD_SUBSURFACE_CUBIC = 1, SHD_SUBSURFACE_GAUSSIAN = 2, - SHD_SUBSURFACE_BURLEY = 3, - SHD_SUBSURFACE_RANDOM_WALK = 4, +#endif + SHD_SUBSURFACE_DIFFUSION = 3, + SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS = 4, + SHD_SUBSURFACE_RANDOM_WALK = 5, }; /* blur node */ diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 61707964191..9ecf94ebd6e 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -135,8 +135,6 @@ .border.xmax = 1.0f, \ .border.ymax = 1.0f, \ \ - .preview_start_resolution = 64, \ - \ .line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE, \ .unit_line_thickness = 1.0f, \ \ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index f2244b4ae61..b28c3ac2b85 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -261,7 +261,7 @@ typedef enum eScenePassType { SCE_PASS_UNUSED_3 = (1 << 4), /* SPEC */ SCE_PASS_SHADOW = (1 << 5), SCE_PASS_AO = (1 << 6), - SCE_PASS_UNUSED_4 = (1 << 7), /* REFLECT */ + SCE_PASS_POSITION = (1 << 7), SCE_PASS_NORMAL = (1 << 8), SCE_PASS_VECTOR = (1 << 9), SCE_PASS_UNUSED_5 = (1 << 10), /* REFRACT */ @@ -293,6 +293,7 @@ typedef enum eScenePassType { #define RE_PASSNAME_COMBINED "Combined" #define RE_PASSNAME_Z "Depth" #define RE_PASSNAME_VECTOR "Vector" +#define RE_PASSNAME_POSITION "Position" #define RE_PASSNAME_NORMAL "Normal" #define RE_PASSNAME_UV "UV" #define RE_PASSNAME_EMIT "Emit" @@ -592,7 +593,7 @@ typedef enum eBakeSaveMode { /** #BakeData.pass_filter */ typedef enum eBakePassFilter { R_BAKE_PASS_FILTER_NONE = 0, - R_BAKE_PASS_FILTER_AO = (1 << 0), + R_BAKE_PASS_FILTER_UNUSED = (1 << 0), R_BAKE_PASS_FILTER_EMIT = (1 << 1), R_BAKE_PASS_FILTER_DIFFUSE = (1 << 2), R_BAKE_PASS_FILTER_GLOSSY = (1 << 3), @@ -653,7 +654,8 @@ typedef struct RenderData { /** * render tile dimensions */ - int tilex, tiley; + int tilex DNA_DEPRECATED; + int tiley DNA_DEPRECATED; short planes DNA_DEPRECATED; short imtype DNA_DEPRECATED; @@ -764,13 +766,10 @@ typedef struct RenderData { /* Cycles baking */ struct BakeData bake; - int preview_start_resolution; + int _pad8; short preview_pixel_size; - /* Type of the debug pass to use. - * Only used when built with debug passes support. - */ - short debug_pass_type; + short _pad4; /* MultiView */ /** SceneRenderView. */ @@ -1887,12 +1886,12 @@ enum { #define R_COMP_CROP (1 << 7) #define R_SCEMODE_UNUSED_8 (1 << 8) /* cleared */ #define R_SINGLE_LAYER (1 << 9) -#define R_EXR_TILE_FILE (1 << 10) +#define R_SCEMODE_UNUSED_10 (1 << 10) /* cleared */ #define R_SCEMODE_UNUSED_11 (1 << 11) /* cleared */ #define R_NO_IMAGE_LOAD (1 << 12) #define R_SCEMODE_UNUSED_13 (1 << 13) /* cleared */ #define R_NO_FRAME_UPDATE (1 << 14) -#define R_FULL_SAMPLE (1 << 15) +#define R_SCEMODE_UNUSED_15 (1 << 15) /* cleared */ #define R_SCEMODE_UNUSED_16 (1 << 16) /* cleared */ #define R_SCEMODE_UNUSED_17 (1 << 17) /* cleared */ #define R_TEXNODE_PREVIEW (1 << 18) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d0bf60d5d02..ec53f35df4c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4665,16 +4665,18 @@ static const EnumPropertyItem node_principled_distribution_items[] = { }; static const EnumPropertyItem node_subsurface_method_items[] = { - {SHD_SUBSURFACE_BURLEY, - "BURLEY", + {SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS, + "RANDOM_WALK_FIXED_RADIUS", 0, - "Christensen-Burley", - "Approximation to physically based volume scattering"}, + "Random Walk (Fixed Radius)", + "Volumetric approximation to physically based volume scattering, using the scattering radius " + "as specified"}, {SHD_SUBSURFACE_RANDOM_WALK, "RANDOM_WALK", 0, "Random Walk", - "Volumetric approximation to physically based volume scattering"}, + "Volumetric approximation to physically based volume scattering, with scattering radius " + "automatically adjusted to match color textures"}, {0, NULL, 0, NULL, NULL}}; /* -- Common nodes ---------------------------------------------------------- */ @@ -6144,35 +6146,12 @@ static void def_sh_ambient_occlusion(StructRNA *srna) static void def_sh_subsurface(StructRNA *srna) { - static const EnumPropertyItem prop_subsurface_falloff_items[] = { - {SHD_SUBSURFACE_CUBIC, "CUBIC", 0, "Cubic", "Simple cubic falloff function"}, - {SHD_SUBSURFACE_GAUSSIAN, - "GAUSSIAN", - 0, - "Gaussian", - "Normal distribution, multiple can be combined to fit more complex profiles"}, - {SHD_SUBSURFACE_BURLEY, - "BURLEY", - 0, - "Christensen-Burley", - "Approximation to physically based volume scattering"}, - {SHD_SUBSURFACE_RANDOM_WALK, - "RANDOM_WALK", - 0, - "Random Walk", - "Volumetric approximation to physically based volume scattering"}, - {0, NULL, 0, NULL, NULL}, - }; - PropertyRNA *prop; prop = RNA_def_property(srna, "falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, prop_subsurface_falloff_items); - RNA_def_property_ui_text(prop, - "Falloff", - "Function to determine how much light nearby points contribute based " - "on their distance to the shading point"); + RNA_def_property_enum_items(prop, node_subsurface_method_items); + RNA_def_property_ui_text(prop, "Method", "Method for rendering subsurface scattering"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); } diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 4400d198b4a..fcb46904e8d 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -52,6 +52,7 @@ const EnumPropertyItem rna_enum_render_pass_type_items[] = { {SCE_PASS_Z, "Z", 0, "Z", ""}, {SCE_PASS_SHADOW, "SHADOW", 0, "Shadow", ""}, {SCE_PASS_AO, "AO", 0, "Ambient Occlusion", ""}, + {SCE_PASS_POSITION, "POSITION", 0, "Position", ""}, {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, {SCE_PASS_VECTOR, "VECTOR", 0, "Vector", ""}, {SCE_PASS_INDEXOB, "OBJECT_INDEX", 0, "Object Index", ""}, @@ -79,6 +80,7 @@ const EnumPropertyItem rna_enum_bake_pass_type_items[] = { {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, {SCE_PASS_AO, "AO", 0, "Ambient Occlusion", ""}, {SCE_PASS_SHADOW, "SHADOW", 0, "Shadow", ""}, + {SCE_PASS_POSITION, "POSITION", 0, "Position", ""}, {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, {SCE_PASS_UV, "UV", 0, "UV", ""}, {SCE_PASS_ROUGHNESS, "ROUGHNESS", 0, "ROUGHNESS", ""}, @@ -177,6 +179,40 @@ static void engine_render(RenderEngine *engine, Depsgraph *depsgraph) RNA_parameter_list_free(&list); } +static void engine_render_frame_finish(RenderEngine *engine) +{ + extern FunctionRNA rna_RenderEngine_render_frame_finish_func; + PointerRNA ptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(NULL, engine->type->rna_ext.srna, engine, &ptr); + func = &rna_RenderEngine_render_frame_finish_func; + + RNA_parameter_list_create(&list, &ptr, func); + engine->type->rna_ext.call(NULL, &ptr, func, &list); + + RNA_parameter_list_free(&list); +} + +static void engine_draw(RenderEngine *engine, const struct bContext *context, Depsgraph *depsgraph) +{ + extern FunctionRNA rna_RenderEngine_draw_func; + PointerRNA ptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(NULL, engine->type->rna_ext.srna, engine, &ptr); + func = &rna_RenderEngine_draw_func; + + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "context", &context); + RNA_parameter_set_lookup(&list, "depsgraph", &depsgraph); + engine->type->rna_ext.call(NULL, &ptr, func, &list); + + RNA_parameter_list_free(&list); +} + static void engine_bake(RenderEngine *engine, struct Depsgraph *depsgraph, struct Object *object, @@ -315,7 +351,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, RenderEngineType *et, dummyet = {NULL}; RenderEngine dummyengine = {NULL}; PointerRNA dummyptr; - int have_function[8]; + int have_function[9]; /* setup dummy engine & engine type to store static properties in */ dummyengine.type = &dummyet; @@ -358,11 +394,13 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, et->update = (have_function[0]) ? engine_update : NULL; et->render = (have_function[1]) ? engine_render : NULL; - et->bake = (have_function[2]) ? engine_bake : NULL; - et->view_update = (have_function[3]) ? engine_view_update : NULL; - et->view_draw = (have_function[4]) ? engine_view_draw : NULL; - et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL; - et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL; + et->render_frame_finish = (have_function[2]) ? engine_render_frame_finish : NULL; + et->draw = (have_function[3]) ? engine_draw : NULL; + et->bake = (have_function[4]) ? engine_bake : NULL; + et->view_update = (have_function[5]) ? engine_view_update : NULL; + et->view_draw = (have_function[6]) ? engine_view_draw : NULL; + et->update_script_node = (have_function[7]) ? engine_update_script_node : NULL; + et->update_render_passes = (have_function[8]) ? engine_update_render_passes : NULL; RE_engines_register(et); @@ -519,6 +557,19 @@ static void rna_def_render_engine(BlenderRNA *brna) parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + func = RNA_def_function(srna, "render_frame_finish", NULL); + RNA_def_function_ui_description( + func, "Perform finishing operations after all view layers in a frame were rendered"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); + + func = RNA_def_function(srna, "draw", NULL); + RNA_def_function_ui_description(func, "Draw render image"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + func = RNA_def_function(srna, "bake", NULL); RNA_def_function_ui_description(func, "Bake passes"); RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); @@ -641,6 +692,14 @@ static void rna_def_render_engine(BlenderRNA *brna) parm = RNA_def_boolean(func, "do_break", 0, "Break", ""); RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "pass_by_index_get", "RE_engine_pass_by_index_get"); + parm = RNA_def_string(func, "layer", NULL, 0, "Layer", "Name of render layer to get pass for"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Index of pass to get", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "render_pass", "RenderPass", "Index", "Index of pass to get"); + RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "active_view_get", "RE_engine_active_view_get"); parm = RNA_def_string(func, "view", NULL, 0, "View", "Single view active"); RNA_def_function_return(func, parm); @@ -761,6 +820,22 @@ static void rna_def_render_engine(BlenderRNA *brna) func = RNA_def_function(srna, "free_blender_memory", "RE_engine_free_blender_memory"); RNA_def_function_ui_description(func, "Free Blender side memory of render engine"); + func = RNA_def_function(srna, "tile_highlight_set", "RE_engine_tile_highlight_set"); + RNA_def_function_ui_description(func, "Set highlighted state of the given tile"); + parm = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "y", 0, 0, INT_MAX, "Y", "", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "width", 0, 0, INT_MAX, "Width", "", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "height", 0, 0, INT_MAX, "Height", "", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, "highlight", 0, "Highlight", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + + func = RNA_def_function(srna, "tile_highlight_clear_all", "RE_engine_tile_highlight_clear_all"); + RNA_def_function_ui_description(func, "Clear highlight from all tiles"); + RNA_define_verify_sdna(0); prop = RNA_def_property(srna, "is_animation", PROP_BOOLEAN, PROP_NONE); @@ -777,11 +852,6 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "layer_override", 1); RNA_def_property_array(prop, 20); - prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "tile_x"); - prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "tile_y"); - prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "resolution_x"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -880,12 +950,6 @@ static void rna_def_render_engine(BlenderRNA *brna) "Don't expose Cycles and Eevee shading nodes in the node editor user " "interface, so own nodes can be used instead"); - prop = RNA_def_property(srna, "bl_use_save_buffers", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SAVE_BUFFERS); - RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - RNA_def_property_ui_text( - prop, "Use Save Buffers", "Support render to an on disk buffer during rendering"); - prop = RNA_def_property(srna, "bl_use_spherical_stereo", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SPHERICAL_STEREO); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 1762b964f8d..e45d39a1ddc 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -532,7 +532,6 @@ const EnumPropertyItem rna_enum_stereo3d_interlace_type_items[] = { const EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { {R_BAKE_PASS_FILTER_NONE, "NONE", 0, "None", ""}, - {R_BAKE_PASS_FILTER_AO, "AO", 0, "Ambient Occlusion", ""}, {R_BAKE_PASS_FILTER_EMIT, "EMIT", 0, "Emit", ""}, {R_BAKE_PASS_FILTER_DIRECT, "DIRECT", 0, "Direct", ""}, {R_BAKE_PASS_FILTER_INDIRECT, "INDIRECT", 0, "Indirect", ""}, @@ -4151,13 +4150,6 @@ void rna_def_view_layer_common(BlenderRNA *brna, StructRNA *srna, const bool sce prop, "Cryptomatte Levels", "Sets how many unique objects can be distinguished per pixel"); RNA_def_property_ui_range(prop, 2.0, 16.0, 2.0, 0.0); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); - - prop = RNA_def_property(srna, "use_pass_cryptomatte_accurate", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "cryptomatte_flag", VIEW_LAYER_CRYPTOMATTE_ACCURATE); - RNA_def_property_boolean_default(prop, true); - RNA_def_property_ui_text( - prop, "Cryptomatte Accurate", "Generate a more accurate cryptomatte pass"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); } prop = RNA_def_property(srna, "use_solid", PROP_BOOLEAN, PROP_NONE); @@ -4251,6 +4243,16 @@ void rna_def_view_layer_common(BlenderRNA *brna, StructRNA *srna, const bool sce RNA_def_property_clear_flag(prop, PROP_EDITABLE); } + prop = RNA_def_property(srna, "use_pass_position", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_POSITION); + RNA_def_property_ui_text(prop, "Position", "Deliver position pass"); + if (scene) { + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + } + else { + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + } + prop = RNA_def_property(srna, "use_pass_normal", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_NORMAL); RNA_def_property_ui_text(prop, "Normal", "Deliver normal pass"); @@ -5122,10 +5124,6 @@ static void rna_def_bake_data(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); /* custom passes flags */ - prop = RNA_def_property(srna, "use_pass_ambient_occlusion", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_AO); - RNA_def_property_ui_text(prop, "Ambient Occlusion", "Add ambient occlusion contribution"); - prop = RNA_def_property(srna, "use_pass_emit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_EMIT); RNA_def_property_ui_text(prop, "Emit", "Add emission contribution"); @@ -5934,29 +5932,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Resolution %", "Percentage scale for render resolution"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneSequencer_update"); - prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_PIXEL); - RNA_def_property_int_sdna(prop, NULL, "tilex"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_range(prop, 8, 65536); - RNA_def_property_ui_text(prop, "Tile X", "Horizontal tile size to use while rendering"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - - prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_PIXEL); - RNA_def_property_int_sdna(prop, NULL, "tiley"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_range(prop, 8, 65536); - RNA_def_property_ui_text(prop, "Tile Y", "Vertical tile size to use while rendering"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - - prop = RNA_def_property(srna, "preview_start_resolution", PROP_INT, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_range(prop, 8, 16384); - RNA_def_property_ui_text(prop, - "Start Resolution", - "Resolution to start rendering preview at, " - "progressively increasing it to the full viewport size"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "preview_pixel_size", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "preview_pixel_size"); RNA_def_property_enum_items(prop, pixel_size_items); @@ -6213,24 +6188,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Movie Format", "When true the format is a movie"); - prop = RNA_def_property(srna, "use_save_buffers", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXR_TILE_FILE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text( - prop, - "Save Buffers", - "Save tiles for all RenderLayers and SceneNodes to files in the temp directory " - "(saves memory, required for Full Sample)"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - - prop = RNA_def_property(srna, "use_full_sample", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_FULL_SAMPLE); - RNA_def_property_ui_text(prop, - "Full Sample", - "Save for every anti-aliasing sample the entire RenderLayer results " - "(this solves anti-aliasing issues with compositing)"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "use_lock_interface", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_lock_interface", 1); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 243300b0a44..a56dfea9dbf 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate cmp_node_rlayers_out[] = { {SOCK_VECTOR, N_(RE_PASSNAME_NORMAL), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_VECTOR, N_(RE_PASSNAME_UV), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_VECTOR, N_(RE_PASSNAME_VECTOR), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_RGBA, N_(RE_PASSNAME_DEPRECATED), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + {SOCK_VECTOR, N_(RE_PASSNAME_POSITION), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_RGBA, N_(RE_PASSNAME_DEPRECATED), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_RGBA, N_(RE_PASSNAME_DEPRECATED), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_RGBA, N_(RE_PASSNAME_SHADOW), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, @@ -72,7 +72,7 @@ static bNodeSocketTemplate cmp_node_rlayers_out[] = { {SOCK_RGBA, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {-1, ""}, }; -#define MAX_LEGACY_SOCKET_INDEX 30 +#define NUM_LEGACY_SOCKETS (ARRAY_SIZE(cmp_node_rlayers_out) - 1) static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node, @@ -382,7 +382,7 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rl break; } } - if (!link && (!rlayer || sock_index > MAX_LEGACY_SOCKET_INDEX)) { + if (!link && (!rlayer || sock_index >= NUM_LEGACY_SOCKETS)) { MEM_freeN(sock->storage); nodeRemoveSocket(ntree, node, sock); } @@ -468,43 +468,12 @@ void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node) const char *node_cmp_rlayers_sock_to_pass(int sock_index) { - const char *sock_to_passname[] = { - RE_PASSNAME_COMBINED, - RE_PASSNAME_COMBINED, - RE_PASSNAME_Z, - RE_PASSNAME_NORMAL, - RE_PASSNAME_UV, - RE_PASSNAME_VECTOR, - RE_PASSNAME_DEPRECATED, - RE_PASSNAME_DEPRECATED, - RE_PASSNAME_DEPRECATED, - RE_PASSNAME_SHADOW, - RE_PASSNAME_AO, - RE_PASSNAME_DEPRECATED, - RE_PASSNAME_DEPRECATED, - RE_PASSNAME_DEPRECATED, - RE_PASSNAME_INDEXOB, - RE_PASSNAME_INDEXMA, - RE_PASSNAME_MIST, - RE_PASSNAME_EMIT, - RE_PASSNAME_ENVIRONMENT, - RE_PASSNAME_DIFFUSE_DIRECT, - RE_PASSNAME_DIFFUSE_INDIRECT, - RE_PASSNAME_DIFFUSE_COLOR, - RE_PASSNAME_GLOSSY_DIRECT, - RE_PASSNAME_GLOSSY_INDIRECT, - RE_PASSNAME_GLOSSY_COLOR, - RE_PASSNAME_TRANSM_DIRECT, - RE_PASSNAME_TRANSM_INDIRECT, - RE_PASSNAME_TRANSM_COLOR, - RE_PASSNAME_SUBSURFACE_DIRECT, - RE_PASSNAME_SUBSURFACE_INDIRECT, - RE_PASSNAME_SUBSURFACE_COLOR, - }; - if (sock_index > MAX_LEGACY_SOCKET_INDEX) { + if (sock_index >= NUM_LEGACY_SOCKETS) { return NULL; } - return sock_to_passname[sock_index]; + const char *name = cmp_node_rlayers_out[sock_index].name; + /* Exception for alpha, which is derived from Combined. */ + return (STREQ(name, "Alpha")) ? RE_PASSNAME_COMBINED : name; } static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c index f601f3e9fd0..06f4d1f1b79 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c @@ -35,6 +35,8 @@ static bNodeSocketTemplate sh_node_bsdf_principled_in[] = { PROP_NONE, SOCK_COMPACT}, {SOCK_RGBA, N_("Subsurface Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + {SOCK_FLOAT, N_("Subsurface IOR"), 1.4f, 0.0f, 0.0f, 0.0f, 1.01f, 3.8f, PROP_FACTOR}, + {SOCK_FLOAT, N_("Subsurface Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, {SOCK_FLOAT, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, {SOCK_FLOAT, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, {SOCK_FLOAT, N_("Specular Tint"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, @@ -74,7 +76,7 @@ static bNodeSocketTemplate sh_node_bsdf_principled_out[] = { static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1 = SHD_GLOSSY_GGX; - node->custom2 = SHD_SUBSURFACE_BURLEY; + node->custom2 = SHD_SUBSURFACE_RANDOM_WALK; } #define socket_not_zero(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) > 1e-5f)) @@ -90,41 +92,40 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, GPUNodeLink *sss_scale; /* Normals */ - if (!in[20].link) { - GPU_link(mat, "world_normals_get", &in[20].link); + if (!in[22].link) { + GPU_link(mat, "world_normals_get", &in[22].link); } /* Clearcoat Normals */ - if (!in[21].link) { - GPU_link(mat, "world_normals_get", &in[21].link); + if (!in[23].link) { + GPU_link(mat, "world_normals_get", &in[23].link); } #if 0 /* Not used at the moment. */ /* Tangents */ - if (!in[22].link) { + if (!in[24].link) { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); - GPU_link(mat, "tangent_orco_z", orco, &in[22].link); + GPU_link(mat, "tangent_orco_z", orco, &in[24].link); GPU_link(mat, "node_tangent", GPU_builtin(GPU_WORLD_NORMAL), - in[22].link, + in[24].link, GPU_builtin(GPU_OBJECT_MATRIX), - &in[22].link); + &in[24].link); } #endif - bool use_diffuse = socket_not_one(4) && socket_not_one(15); + bool use_diffuse = socket_not_one(6) && socket_not_one(17); bool use_subsurf = socket_not_zero(1) && use_diffuse && node->sss_id > 0; - bool use_refract = socket_not_one(4) && socket_not_zero(15); - bool use_clear = socket_not_zero(12); + bool use_refract = socket_not_one(6) && socket_not_zero(17); + bool use_clear = socket_not_zero(14); /* SSS Profile */ if (use_subsurf) { - static short profile = SHD_SUBSURFACE_BURLEY; bNodeSocket *socket = BLI_findlink(&node->original->inputs, 2); bNodeSocketValueRGBA *socket_data = socket->default_value; /* For some reason it seems that the socket value is in ARGB format. */ - GPU_material_sss_profile_create(mat, &socket_data->value[1], &profile, NULL); + GPU_material_sss_profile_create(mat, &socket_data->value[1]); } if (in[2].link) { diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c index 4b91bcbd11c..e917858e0f2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c @@ -25,8 +25,8 @@ static bNodeSocketTemplate sh_node_subsurface_scattering_in[] = { {SOCK_RGBA, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, {SOCK_FLOAT, N_("Scale"), 1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, {SOCK_VECTOR, N_("Radius"), 1.0f, 0.2f, 0.1f, 0.0f, 0.0f, 100.0f, PROP_NONE, SOCK_COMPACT}, - {SOCK_FLOAT, N_("Sharpness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - {SOCK_FLOAT, N_("Texture Blur"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + {SOCK_FLOAT, N_("IOR"), 1.4f, 0.0f, 0.0f, 0.0f, 1.01f, 3.8f, PROP_FACTOR}, + {SOCK_FLOAT, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, {-1, ""}, }; @@ -38,7 +38,8 @@ static bNodeSocketTemplate sh_node_subsurface_scattering_out[] = { static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node) { - node->custom1 = SHD_SUBSURFACE_BURLEY; + node->custom1 = SHD_SUBSURFACE_RANDOM_WALK; + node->custom2 = true; } static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, @@ -54,11 +55,8 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, if (node->sss_id > 0) { bNodeSocket *socket = BLI_findlink(&node->original->inputs, 2); bNodeSocketValueRGBA *socket_data = socket->default_value; - bNodeSocket *socket_sharp = BLI_findlink(&node->original->inputs, 3); - bNodeSocketValueFloat *socket_data_sharp = socket_sharp->default_value; /* For some reason it seems that the socket value is in ARGB format. */ - GPU_material_sss_profile_create( - mat, &socket_data->value[1], &node->original->custom1, &socket_data_sharp->value); + GPU_material_sss_profile_create(mat, &socket_data->value[1]); /* sss_id is 0 only the node is not connected to any output. * In this case flagging the material would trigger a bug (see T68736). */ @@ -69,23 +67,6 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, mat, node, "node_subsurface_scattering", in, out, GPU_constant(&node->sss_id)); } -static void node_shader_update_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node) -{ - bNodeSocket *sock; - int falloff = node->custom1; - - for (sock = node->inputs.first; sock; sock = sock->next) { - if (STREQ(sock->name, "Sharpness")) { - if (falloff == SHD_SUBSURFACE_CUBIC) { - sock->flag &= ~SOCK_UNAVAIL; - } - else { - sock->flag |= SOCK_UNAVAIL; - } - } - } -} - /* node type definition */ void register_node_type_sh_subsurface_scattering(void) { @@ -99,7 +80,6 @@ void register_node_type_sh_subsurface_scattering(void) node_type_init(&ntype, node_shader_init_subsurface_scattering); node_type_storage(&ntype, "", NULL, NULL); node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering); - node_type_update(&ntype, node_shader_update_subsurface_scattering); nodeRegisterType(&ntype); } diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 0046474d064..494415a4077 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -59,7 +59,6 @@ set(SRC RE_pipeline.h RE_texture.h - intern/initrender.h intern/pipeline.h intern/render_result.h intern/render_types.h diff --git a/source/blender/render/RE_engine.h b/source/blender/render/RE_engine.h index dfc0d5d0e9f..2a3a5964262 100644 --- a/source/blender/render/RE_engine.h +++ b/source/blender/render/RE_engine.h @@ -40,6 +40,7 @@ struct RenderData; struct RenderEngine; struct RenderEngineType; struct RenderLayer; +struct RenderPass; struct RenderResult; struct ReportList; struct Scene; @@ -59,7 +60,7 @@ extern "C" { #define RE_USE_PREVIEW 4 #define RE_USE_POSTPROCESS 8 #define RE_USE_EEVEE_VIEWPORT 16 -#define RE_USE_SAVE_BUFFERS 32 +/* #define RE_USE_SAVE_BUFFERS_DEPRECATED 32 */ #define RE_USE_SHADING_NODES_CUSTOM 64 #define RE_USE_SPHERICAL_STEREO 128 #define RE_USE_STEREO_VIEWPORT 256 @@ -75,6 +76,7 @@ extern "C" { #define RE_ENGINE_DO_UPDATE 8 #define RE_ENGINE_RENDERING 16 #define RE_ENGINE_HIGHLIGHT_TILES 32 +#define RE_ENGINE_CAN_DRAW 64 extern ListBase R_engines; @@ -87,7 +89,20 @@ typedef struct RenderEngineType { int flag; void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph); + void (*render)(struct RenderEngine *engine, struct Depsgraph *depsgraph); + + /* Offline rendering is finished - no more view layers will be rendered. + * + * All the pending data is to be communicated from the engine back to Blender. In a possibly + * most memory-efficient manner (engine might free its database before making Blender to allocate + * full-frame render result). */ + void (*render_frame_finish)(struct RenderEngine *engine); + + void (*draw)(struct RenderEngine *engine, + const struct bContext *context, + struct Depsgraph *depsgraph); + void (*bake)(struct RenderEngine *engine, struct Depsgraph *depsgraph, struct Object *object, @@ -132,9 +147,6 @@ typedef struct RenderEngine { struct Object *camera_override; unsigned int layer_override; - int tile_x; - int tile_y; - struct Render *re; ListBase fullresult; char text[512]; /* IMA_MAX_RENDER_TEXT */ @@ -189,6 +201,10 @@ void RE_engine_end_result(RenderEngine *engine, bool merge_results); struct RenderResult *RE_engine_get_result(struct RenderEngine *engine); +struct RenderPass *RE_engine_pass_by_index_get(struct RenderEngine *engine, + const char *layer_name, + int index); + const char *RE_engine_active_view_get(RenderEngine *engine); void RE_engine_active_view_set(RenderEngine *engine, const char *viewname); float RE_engine_get_camera_shift_x(RenderEngine *engine, @@ -228,6 +244,24 @@ void RE_engine_register_pass(struct RenderEngine *engine, bool RE_engine_use_persistent_data(struct RenderEngine *engine); +struct RenderEngine *RE_engine_get(const struct Render *re); + +/* Acquire render engine for drawing via its `draw()` callback. + * + * If drawing is not possible false is returned. If drawing is possible then the engine is + * "acquired" so that it can not be freed by the render pipeline. + * + * Drawing is possible if the engine has the `draw()` callback and it is in its `render()` + * callback. */ +bool RE_engine_draw_acquire(struct Render *re); +void RE_engine_draw_release(struct Render *re); + +/* NOTE: Only used for Cycles's BLenderGPUDisplay integration with the draw manager. A subject + * for re-consideration. Do not use this functionality. */ +bool RE_engine_has_render_context(struct RenderEngine *engine); +void RE_engine_render_context_enable(struct RenderEngine *engine); +void RE_engine_render_context_disable(struct RenderEngine *engine); + /* Engine Types */ void RE_engines_init(void); @@ -252,6 +286,10 @@ void RE_bake_engine_set_engine_parameters(struct Render *re, void RE_engine_free_blender_memory(struct RenderEngine *engine); +void RE_engine_tile_highlight_set( + struct RenderEngine *engine, int x, int y, int width, int height, bool highlight); +void RE_engine_tile_highlight_clear_all(struct RenderEngine *engine); + #ifdef __cplusplus } #endif diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h index cd839385bfb..3237772dd80 100644 --- a/source/blender/render/RE_pipeline.h +++ b/source/blender/render/RE_pipeline.h @@ -141,9 +141,6 @@ typedef struct RenderResult { volatile rcti renrect; volatile RenderLayer *renlay; - /* optional saved endresult on disk */ - int do_exr_tile; - /* for render results in Image, verify validity for sequences */ int framenr; diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c index 76839651b5d..0f893ce8cd5 100644 --- a/source/blender/render/intern/bake.c +++ b/source/blender/render/intern/bake.c @@ -774,18 +774,6 @@ void RE_bake_pixels_populate(Mesh *me, /* ******************** NORMALS ************************ */ -/** - * convert a normalized normal to the -1.0 1.0 range - * the input is expected to be POS_X, POS_Y, POS_Z - */ -static void normal_uncompress(float out[3], const float in[3]) -{ - int i; - for (i = 0; i < 3; i++) { - out[i] = 2.0f * in[i] - 1.0f; - } -} - static void normal_compress(float out[3], const float in[3], const eBakeNormalSwizzle normal_swizzle[3]) @@ -934,7 +922,7 @@ void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[], copy_v3_v3(tsm[2], normal); /* texture values */ - normal_uncompress(nor, &result[offset]); + copy_v3_v3(nor, &result[offset]); /* converts from world space to local space */ mul_transposed_mat3_m4_v3(mat, nor); @@ -976,7 +964,7 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[], } offset = i * depth; - normal_uncompress(nor, &result[offset]); + copy_v3_v3(nor, &result[offset]); /* rotates only without translation */ mul_mat3_m4_v3(iobmat, nor); @@ -1004,7 +992,7 @@ void RE_bake_normal_world_to_world(const BakePixel pixel_array[], } offset = i * depth; - normal_uncompress(nor, &result[offset]); + copy_v3_v3(nor, &result[offset]); /* save back the values */ normal_compress(&result[offset], nor, normal_swizzle); @@ -1053,6 +1041,7 @@ int RE_pass_depth(const eScenePassType pass_type) } case SCE_PASS_COMBINED: case SCE_PASS_SHADOW: + case SCE_PASS_POSITION: case SCE_PASS_NORMAL: case SCE_PASS_VECTOR: case SCE_PASS_INDEXOB: /* XXX double check */ diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c index 5728b784714..389b821ca35 100644 --- a/source/blender/render/intern/engine.c +++ b/source/blender/render/intern/engine.c @@ -62,7 +62,6 @@ #include "DRW_engine.h" -#include "initrender.h" #include "pipeline.h" #include "render_result.h" #include "render_types.h" @@ -283,14 +282,6 @@ static void render_result_to_bake(RenderEngine *engine, RenderResult *rr) /* Render Results */ -static RenderPart *get_part_from_result(Render *re, RenderResult *result) -{ - rcti key = result->tilerect; - BLI_rcti_translate(&key, re->disprect.xmin, re->disprect.ymin); - - return BLI_ghash_lookup(re->parts, &key); -} - static HighlightedTile highlighted_tile_from_result_get(Render *re, RenderResult *result) { HighlightedTile tile; @@ -300,6 +291,37 @@ static HighlightedTile highlighted_tile_from_result_get(Render *re, RenderResult return tile; } +static void engine_tile_highlight_set(RenderEngine *engine, + const HighlightedTile *tile, + bool highlight) +{ + if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { + return; + } + + Render *re = engine->re; + + BLI_mutex_lock(&re->highlighted_tiles_mutex); + + if (re->highlighted_tiles == NULL) { + re->highlighted_tiles = BLI_gset_new( + BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, "highlighted tiles"); + } + + if (highlight) { + HighlightedTile **tile_in_set; + if (!BLI_gset_ensure_p_ex(re->highlighted_tiles, tile, (void ***)&tile_in_set)) { + *tile_in_set = MEM_mallocN(sizeof(HighlightedTile), __func__); + **tile_in_set = *tile; + } + } + else { + BLI_gset_remove(re->highlighted_tiles, tile, MEM_freeN); + } + + BLI_mutex_unlock(&re->highlighted_tiles_mutex); +} + RenderResult *RE_engine_begin_result( RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname) { @@ -332,7 +354,7 @@ RenderResult *RE_engine_begin_result( disprect.ymin = y; disprect.ymax = y + h; - result = render_result_new(re, &disprect, RR_USE_MEM, layername, viewname); + result = render_result_new(re, &disprect, layername, viewname); /* TODO: make this thread safe. */ @@ -341,25 +363,12 @@ RenderResult *RE_engine_begin_result( render_result_clone_passes(re, result, viewname); render_result_passes_allocated_ensure(result); - RenderPart *pa; - - /* Copy EXR tile settings, so pipeline knows whether this is a result - * for Save Buffers enabled rendering. - */ - result->do_exr_tile = re->result->do_exr_tile; - BLI_addtail(&engine->fullresult, result); result->tilerect.xmin += re->disprect.xmin; result->tilerect.xmax += re->disprect.xmin; result->tilerect.ymin += re->disprect.ymin; result->tilerect.ymax += re->disprect.ymin; - - pa = get_part_from_result(re, result); - - if (pa) { - pa->status = PART_STATUS_IN_PROGRESS; - } } return result; @@ -426,53 +435,14 @@ void RE_engine_end_result( re_ensure_passes_allocated_thread_safe(re); - /* merge. on break, don't merge in result for preview renders, looks nicer */ - if (!highlight) { - /* for exr tile render, detect tiles that are done */ - RenderPart *pa = get_part_from_result(re, result); - - if (pa) { - pa->status = (!cancel && merge_results) ? PART_STATUS_MERGED : PART_STATUS_RENDERED; - } - else if (re->result->do_exr_tile) { - /* If written result does not match any tile and we are using save - * buffers, we are going to get OpenEXR save errors. */ - fprintf(stderr, "RenderEngine.end_result: dimensions do not match any OpenEXR tile.\n"); - } - } - if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES)) { - BLI_mutex_lock(&re->highlighted_tiles_mutex); - - if (re->highlighted_tiles == NULL) { - re->highlighted_tiles = BLI_gset_new( - BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, "highlighted tiles"); - } + const HighlightedTile tile = highlighted_tile_from_result_get(re, result); - HighlightedTile tile = highlighted_tile_from_result_get(re, result); - if (highlight) { - void **tile_in_set; - if (!BLI_gset_ensure_p_ex(re->highlighted_tiles, &tile, &tile_in_set)) { - *tile_in_set = MEM_mallocN(sizeof(HighlightedTile), __func__); - memcpy(*tile_in_set, &tile, sizeof(tile)); - } - BLI_gset_add(re->highlighted_tiles, &tile); - } - else { - BLI_gset_remove(re->highlighted_tiles, &tile, MEM_freeN); - } - - BLI_mutex_unlock(&re->highlighted_tiles_mutex); + engine_tile_highlight_set(engine, &tile, highlight); } if (!cancel || merge_results) { - if (re->result->do_exr_tile) { - if (!cancel && merge_results) { - render_result_exr_file_merge(re->result, result, re->viewname); - render_result_merge(re->result, result); - } - } - else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW))) { + if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW))) { render_result_merge(re->result, result); } @@ -582,6 +552,27 @@ void RE_engine_set_error_message(RenderEngine *engine, const char *msg) } } +RenderPass *RE_engine_pass_by_index_get(RenderEngine *engine, const char *layer_name, int index) +{ + Render *re = engine->re; + if (re == NULL) { + return NULL; + } + + RenderPass *pass = NULL; + + RenderResult *rr = RE_AcquireResultRead(re); + if (rr != NULL) { + const RenderLayer *layer = RE_GetRenderLayer(rr, layer_name); + if (layer != NULL) { + pass = BLI_findlink(&layer->passes, index); + } + } + RE_ReleaseResult(re); + + return pass; +} + const char *RE_engine_active_view_get(RenderEngine *engine) { Render *re = engine->re; @@ -837,12 +828,6 @@ bool RE_bake_engine(Render *re, engine->resolution_x = re->winx; engine->resolution_y = re->winy; - BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); - RE_parts_init(re); - engine->tile_x = re->r.tilex; - engine->tile_y = re->r.tiley; - BLI_rw_mutex_unlock(&re->partsmutex); - if (type->bake) { engine->depsgraph = depsgraph; @@ -870,21 +855,13 @@ bool RE_bake_engine(Render *re, engine->depsgraph = NULL; } - engine->tile_x = 0; - engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; - /* Free depsgraph outside of parts mutex lock, since this locks OpenGL context - * while the UI drawing might also lock the OpenGL context and parts mutex. */ engine_depsgraph_free(engine); - BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); RE_engine_free(engine); re->engine = NULL; - RE_parts_free(re); - BLI_rw_mutex_unlock(&re->partsmutex); - if (BKE_reports_contain(re->reports, RPT_ERROR)) { G.is_break = true; } @@ -928,15 +905,23 @@ static void engine_render_view_layer(Render *re, DRW_render_context_enable(engine->re); } + BLI_mutex_lock(&engine->re->engine_draw_mutex); + re->engine->flag |= RE_ENGINE_CAN_DRAW; + BLI_mutex_unlock(&engine->re->engine_draw_mutex); + engine->type->render(engine, engine->depsgraph); + BLI_mutex_lock(&engine->re->engine_draw_mutex); + re->engine->flag &= ~RE_ENGINE_CAN_DRAW; + BLI_mutex_unlock(&engine->re->engine_draw_mutex); + if (use_gpu_context) { DRW_render_context_disable(engine->re); } } /* Optionally composite grease pencil over render result. */ - if (engine->has_grease_pencil && use_grease_pencil && !re->result->do_exr_tile) { + if (engine->has_grease_pencil && use_grease_pencil) { /* NOTE: External engine might have been requested to free its * dependency graph, which is only allowed if there is no grease * pencil (pipeline is taking care of that). */ @@ -981,16 +966,11 @@ bool RE_engine_render(Render *re, bool do_all) /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) { - int savebuffers = RR_USE_MEM; - if (re->result) { render_result_free(re->result); } - if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE)) { - savebuffers = RR_USE_EXR; - } - re->result = render_result_new(re, &re->disprect, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); } BLI_rw_mutex_unlock(&re->resultmutex); @@ -1035,32 +1015,15 @@ bool RE_engine_render(Render *re, bool do_all) engine->resolution_x = re->winx; engine->resolution_y = re->winy; - BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); - RE_parts_init(re); - engine->tile_x = re->partx; - engine->tile_y = re->party; - BLI_rw_mutex_unlock(&re->partsmutex); - - if (re->result->do_exr_tile) { - render_result_exr_file_begin(re, engine); - } - /* Clear UI drawing locks. */ if (re->draw_lock) { re->draw_lock(re->dlh, false); } - /* Render view layers. */ - bool delay_grease_pencil = false; - if (type->render) { FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer_iter) { engine_render_view_layer(re, engine, view_layer_iter, true, true); - /* With save buffers there is no render buffer in memory for compositing, delay - * grease pencil in that case. */ - delay_grease_pencil = engine->has_grease_pencil && re->result->do_exr_tile; - if (RE_engine_test_break(engine)) { break; } @@ -1068,42 +1031,18 @@ bool RE_engine_render(Render *re, bool do_all) FOREACH_VIEW_LAYER_TO_RENDER_END; } + if (type->render_frame_finish) { + type->render_frame_finish(engine); + } + /* Clear tile data */ - engine->tile_x = 0; - engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; render_result_free_list(&engine->fullresult, engine->fullresult.first); - BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); - - /* For save buffers, read back from disk. */ - if (re->result->do_exr_tile) { - render_result_exr_file_end(re, engine); - } - - /* Perform delayed grease pencil rendering. */ - if (delay_grease_pencil) { - BLI_rw_mutex_unlock(&re->partsmutex); - - FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer_iter) { - engine_render_view_layer(re, engine, view_layer_iter, false, true); - if (RE_engine_test_break(engine)) { - break; - } - } - FOREACH_VIEW_LAYER_TO_RENDER_END; - - BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); - } - /* re->engine becomes zero if user changed active render engine during render */ if (!engine_keep_depsgraph(engine) || !re->engine) { - /* Free depsgraph outside of parts mutex lock, since this locks OpenGL context - * while the UI drawing might also lock the OpenGL context and parts mutex. */ - BLI_rw_mutex_unlock(&re->partsmutex); engine_depsgraph_free(engine); - BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); RE_engine_free(engine); re->engine = NULL; @@ -1115,9 +1054,6 @@ bool RE_engine_render(Render *re, bool do_all) BLI_rw_mutex_unlock(&re->resultmutex); } - RE_parts_free(re); - BLI_rw_mutex_unlock(&re->partsmutex); - if (BKE_reports_contain(re->reports, RPT_ERROR)) { G.is_break = true; } @@ -1179,3 +1115,81 @@ void RE_engine_free_blender_memory(RenderEngine *engine) } engine_depsgraph_free(engine); } + +struct RenderEngine *RE_engine_get(const Render *re) +{ + return re->engine; +} + +bool RE_engine_draw_acquire(Render *re) +{ + BLI_mutex_lock(&re->engine_draw_mutex); + + RenderEngine *engine = re->engine; + + if (engine == NULL || engine->type->draw == NULL || (engine->flag & RE_ENGINE_CAN_DRAW) == 0) { + BLI_mutex_unlock(&re->engine_draw_mutex); + return false; + } + + return true; +} + +void RE_engine_draw_release(Render *re) +{ + BLI_mutex_unlock(&re->engine_draw_mutex); +} + +void RE_engine_tile_highlight_set( + RenderEngine *engine, int x, int y, int width, int height, bool highlight) +{ + HighlightedTile tile; + BLI_rcti_init(&tile.rect, x, x + width, y, y + height); + + engine_tile_highlight_set(engine, &tile, highlight); +} + +void RE_engine_tile_highlight_clear_all(RenderEngine *engine) +{ + if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { + return; + } + + Render *re = engine->re; + + BLI_mutex_lock(&re->highlighted_tiles_mutex); + + if (re->highlighted_tiles != NULL) { + BLI_gset_clear(re->highlighted_tiles, MEM_freeN); + } + + BLI_mutex_unlock(&re->highlighted_tiles_mutex); +} + +/* -------------------------------------------------------------------- */ +/** \name OpenGL context manipulation. + * + * NOTE: Only used for Cycles's BLenderGPUDisplay integration with the draw manager. A subject + * for re-consideration. Do not use this functionality. + * \{ */ + +bool RE_engine_has_render_context(RenderEngine *engine) +{ + if (engine->re == NULL) { + return false; + } + + return RE_gl_context_get(engine->re) != NULL; +} + +void RE_engine_render_context_enable(RenderEngine *engine) +{ + DRW_render_context_enable(engine->re); +} + +void RE_engine_render_context_disable(RenderEngine *engine) +{ + DRW_render_context_disable(engine->re); +} + +/** \} */ diff --git a/source/blender/render/intern/initrender.c b/source/blender/render/intern/initrender.c index 3148625c866..2370d8e893b 100644 --- a/source/blender/render/intern/initrender.c +++ b/source/blender/render/intern/initrender.c @@ -43,9 +43,6 @@ #include "pipeline.h" #include "render_types.h" -/* Own includes */ -#include "initrender.h" - /* ****************** MASKS and LUTS **************** */ static float filt_quadratic(float x) @@ -244,91 +241,3 @@ void RE_GetViewPlane(Render *re, rctf *r_viewplane, rcti *r_disprect) BLI_rcti_init(r_disprect, 0, 0, 0, 0); } } - -/* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ - -void RE_parts_free(Render *re) -{ - if (re->parts) { - BLI_ghash_free(re->parts, NULL, MEM_freeN); - re->parts = NULL; - } -} - -void RE_parts_clamp(Render *re) -{ - /* part size */ - re->partx = max_ii(1, min_ii(re->r.tilex, re->rectx)); - re->party = max_ii(1, min_ii(re->r.tiley, re->recty)); -} - -void RE_parts_init(Render *re) -{ - int nr, xd, yd, partx, party, xparts, yparts; - int xminb, xmaxb, yminb, ymaxb; - - RE_parts_free(re); - - re->parts = BLI_ghash_new( - BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, "render parts"); - - /* Just for readable code. */ - xminb = re->disprect.xmin; - yminb = re->disprect.ymin; - xmaxb = re->disprect.xmax; - ymaxb = re->disprect.ymax; - - RE_parts_clamp(re); - - partx = re->partx; - party = re->party; - /* part count */ - xparts = (re->rectx + partx - 1) / partx; - yparts = (re->recty + party - 1) / party; - - for (nr = 0; nr < xparts * yparts; nr++) { - rcti disprect; - int rectx, recty; - - xd = (nr % xparts); - yd = (nr - xd) / xparts; - - disprect.xmin = xminb + xd * partx; - disprect.ymin = yminb + yd * party; - - /* ensure we cover the entire picture, so last parts go to end */ - if (xd < xparts - 1) { - disprect.xmax = disprect.xmin + partx; - if (disprect.xmax > xmaxb) { - disprect.xmax = xmaxb; - } - } - else { - disprect.xmax = xmaxb; - } - - if (yd < yparts - 1) { - disprect.ymax = disprect.ymin + party; - if (disprect.ymax > ymaxb) { - disprect.ymax = ymaxb; - } - } - else { - disprect.ymax = ymaxb; - } - - rectx = BLI_rcti_size_x(&disprect); - recty = BLI_rcti_size_y(&disprect); - - /* so, now can we add this part? */ - if (rectx > 0 && recty > 0) { - RenderPart *pa = MEM_callocN(sizeof(RenderPart), "new part"); - - pa->disprect = disprect; - pa->rectx = rectx; - pa->recty = recty; - - BLI_ghash_insert(re->parts, &pa->disprect, pa); - } - } -} diff --git a/source/blender/render/intern/initrender.h b/source/blender/render/intern/initrender.h deleted file mode 100644 index f5ac352752f..00000000000 --- a/source/blender/render/intern/initrender.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - */ - -/** \file - * \ingroup render - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -/* Functions */ - -void RE_parts_init(Render *re); -void RE_parts_free(Render *re); -void RE_parts_clamp(Render *re); - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 5418f4035b1..72ff920561d 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -102,7 +102,6 @@ #include "DEG_depsgraph.h" /* internal */ -#include "initrender.h" #include "pipeline.h" #include "render_result.h" #include "render_types.h" @@ -568,7 +567,7 @@ Render *RE_NewRender(const char *name) BLI_addtail(&RenderGlobal.renderlist, re); BLI_strncpy(re->name, name, RE_MAXNAME); BLI_rw_mutex_init(&re->resultmutex); - BLI_rw_mutex_init(&re->partsmutex); + BLI_mutex_init(&re->engine_draw_mutex); BLI_mutex_init(&re->highlighted_tiles_mutex); } @@ -633,7 +632,7 @@ void RE_FreeRender(Render *re) } BLI_rw_mutex_end(&re->resultmutex); - BLI_rw_mutex_end(&re->partsmutex); + BLI_mutex_end(&re->engine_draw_mutex); BLI_mutex_end(&re->highlighted_tiles_mutex); BLI_freelistN(&re->view_layers); @@ -722,26 +721,6 @@ void RE_FreePersistentData(const Scene *scene) /* ********* initialize state ******** */ -/* clear full sample and tile flags if needed */ -static int check_mode_full_sample(RenderData *rd) -{ - int scemode = rd->scemode; - - /* not supported by any current renderer */ - scemode &= ~R_FULL_SAMPLE; - -#ifdef WITH_OPENEXR - if (scemode & R_FULL_SAMPLE) { - scemode |= R_EXR_TILE_FILE; /* enable automatic */ - } -#else - /* can't do this without openexr support */ - scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE); -#endif - - return scemode; -} - static void re_init_resolution(Render *re, Render *source, int winx, int winy, rcti *disprect) { re->winx = winx; @@ -839,8 +818,6 @@ void RE_InitState(Render *re, return; } - re->r.scemode = check_mode_full_sample(&re->r); - if (single_layer) { int index = BLI_findindex(render_layers, single_layer); if (index != -1) { @@ -890,9 +867,6 @@ void RE_InitState(Render *re, render_result_view_new(re->result, ""); } - /* ensure renderdatabase can use part settings correct */ - RE_parts_clamp(re); - BLI_rw_mutex_unlock(&re->resultmutex); RE_init_threadcount(re); @@ -1040,7 +1014,7 @@ static void render_result_uncrop(Render *re) /* weak is: it chances disprect from border */ render_result_disprect_to_full_resolution(re); - rres = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + rres = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); render_result_passes_allocated_ensure(rres); rres->stamp_data = BKE_stamp_data_copy(re->result->stamp_data); @@ -1227,7 +1201,7 @@ static void do_render_compositor(Render *re) if ((re->r.mode & R_CROP) == 0) { render_result_disprect_to_full_resolution(re); } - re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); BLI_rw_mutex_unlock(&re->resultmutex); @@ -1647,7 +1621,7 @@ bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *reports) { - int scemode = check_mode_full_sample(&scene->r); + const int scemode = scene->r.scemode; if (scene->r.mode & R_BORDER) { if (scene->r.border.xmax <= scene->r.border.xmin || @@ -1657,17 +1631,6 @@ bool RE_is_rendering_allowed(Scene *scene, } } - if (scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) { - char str[FILE_MAX]; - - render_result_exr_file_path(scene, "", 0, str); - - if (!BLI_file_is_writable(str)) { - BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path"); - return 0; - } - } - if (RE_seq_render_active(scene, &scene->r)) { /* Sequencer */ if (scene->r.mode & R_BORDER) { @@ -1686,13 +1649,6 @@ bool RE_is_rendering_allowed(Scene *scene, BKE_report(reports, RPT_ERROR, "No render output node in scene"); return 0; } - - if (scemode & R_FULL_SAMPLE) { - if (compositor_needs_render(scene, 0) == 0) { - BKE_report(reports, RPT_ERROR, "Full sample AA not supported without 3D rendering"); - return 0; - } - } } else { /* Regular Render */ @@ -1710,14 +1666,6 @@ bool RE_is_rendering_allowed(Scene *scene, return 1; } -static void validate_render_settings(Render *re) -{ - if (RE_engine_is_external(re)) { - /* not supported yet */ - re->r.scemode &= ~R_FULL_SAMPLE; - } -} - static void update_physics_cache(Render *re, Scene *scene, ViewLayer *view_layer, @@ -1820,8 +1768,6 @@ static int render_init_from_main(Render *re, /* initstate makes new result, have to send changed tags around */ ntreeCompositTagRender(re->scene); - validate_render_settings(re); - re->display_init(re->dih, re->result); re->display_clear(re->dch, re->result); diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index 6cb6aabe885..c308147fc5b 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -260,8 +260,10 @@ RenderPass *render_layer_add_pass(RenderResult *rr, /* will read info from Render *re to define layers */ /* called in threads */ /* re->winx,winy is coordinate space of entire image, partrct the part within */ -RenderResult *render_result_new( - Render *re, rcti *partrct, int savebuffers, const char *layername, const char *viewname) +RenderResult *render_result_new(Render *re, + rcti *partrct, + const char *layername, + const char *viewname) { RenderResult *rr; RenderLayer *rl; @@ -287,10 +289,6 @@ RenderResult *render_result_new( rr->tilerect.ymin = partrct->ymin - re->disprect.ymin; rr->tilerect.ymax = partrct->ymax - re->disprect.ymin; - if (savebuffers) { - rr->do_exr_tile = true; - } - rr->passes_allocated = false; render_result_views_new(rr, &re->r); @@ -314,10 +312,6 @@ RenderResult *render_result_new( rl->rectx = rectx; rl->recty = recty; - if (rr->do_exr_tile) { - rl->exrhandle = IMB_exr_get_handle(); - } - for (rv = rr->views.first; rv; rv = rv->next) { const char *view = rv->name; @@ -327,10 +321,6 @@ RenderResult *render_result_new( } } - if (rr->do_exr_tile) { - IMB_exr_add_view(rl->exrhandle, view); - } - #define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \ do { \ if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \ @@ -351,6 +341,9 @@ RenderResult *render_result_new( if (view_layer->passflag & SCE_PASS_NORMAL) { RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ"); } + if (view_layer->passflag & SCE_PASS_POSITION) { + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_POSITION, view, "XYZ"); + } if (view_layer->passflag & SCE_PASS_UV) { RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA"); } @@ -424,11 +417,6 @@ RenderResult *render_result_new( rl->rectx = rectx; rl->recty = recty; - /* duplicate code... */ - if (rr->do_exr_tile) { - rl->exrhandle = IMB_exr_get_handle(); - } - for (rv = rr->views.first; rv; rv = rv->next) { const char *view = rv->name; @@ -438,10 +426,6 @@ RenderResult *render_result_new( } } - if (rr->do_exr_tile) { - IMB_exr_add_view(rl->exrhandle, view); - } - /* a renderlayer should always have a Combined pass */ render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA"); } @@ -1089,227 +1073,6 @@ void render_result_single_layer_end(Render *re) re->pushedresult = NULL; } -/************************* EXR Tile File Rendering ***************************/ - -static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname) -{ - RenderLayer *rlp, *rl; - RenderPass *rpassp; - int partx, party; - - BLI_thread_lock(LOCK_IMAGE); - - for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { - rl = RE_GetRenderLayer(rr, rlp->name); - - /* should never happen but prevents crash if it does */ - BLI_assert(rl); - if (UNLIKELY(rl == NULL)) { - continue; - } - - /* passes are allocated in sync */ - for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) { - const int xstride = rpassp->channels; - int a; - char fullname[EXR_PASS_MAXNAME]; - - for (a = 0; a < xstride; a++) { - set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id); - - IMB_exr_set_channel(rl->exrhandle, - rlp->name, - fullname, - xstride, - xstride * rrpart->rectx, - rpassp->rect + a); - } - } - } - - party = rrpart->tilerect.ymin; - partx = rrpart->tilerect.xmin; - - for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { - rl = RE_GetRenderLayer(rr, rlp->name); - - /* should never happen but prevents crash if it does */ - BLI_assert(rl); - if (UNLIKELY(rl == NULL)) { - continue; - } - - IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname, false); - } - - BLI_thread_unlock(LOCK_IMAGE); -} - -void render_result_save_empty_result_tiles(Render *re) -{ - RenderResult *rr; - RenderLayer *rl; - - for (rr = re->result; rr; rr = rr->next) { - for (rl = rr->layers.first; rl; rl = rl->next) { - GHashIterator pa_iter; - GHASH_ITER (pa_iter, re->parts) { - RenderPart *pa = BLI_ghashIterator_getValue(&pa_iter); - if (pa->status != PART_STATUS_MERGED) { - int party = pa->disprect.ymin - re->disprect.ymin; - int partx = pa->disprect.xmin - re->disprect.xmin; - IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname, true); - } - } - } - } -} - -/* Compute list of passes needed by render engine. */ -static void templates_register_pass_cb(void *userdata, - Scene *UNUSED(scene), - ViewLayer *UNUSED(view_layer), - const char *name, - int channels, - const char *chan_id, - eNodeSocketDatatype UNUSED(type)) -{ - ListBase *templates = userdata; - RenderPass *pass = MEM_callocN(sizeof(RenderPass), "RenderPassTemplate"); - - pass->channels = channels; - BLI_strncpy(pass->name, name, sizeof(pass->name)); - BLI_strncpy(pass->chan_id, chan_id, sizeof(pass->chan_id)); - - BLI_addtail(templates, pass); -} - -static void render_result_get_pass_templates(RenderEngine *engine, - Render *re, - RenderLayer *rl, - ListBase *templates) -{ - BLI_listbase_clear(templates); - - if (engine && engine->type->update_render_passes) { - ViewLayer *view_layer = BLI_findstring(&re->view_layers, rl->name, offsetof(ViewLayer, name)); - if (view_layer) { - RE_engine_update_render_passes( - engine, re->scene, view_layer, templates_register_pass_cb, templates); - } - } -} - -/* begin write of exr tile file */ -void render_result_exr_file_begin(Render *re, RenderEngine *engine) -{ - char str[FILE_MAX]; - - for (RenderResult *rr = re->result; rr; rr = rr->next) { - LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) { - /* Get passes needed by engine. Normally we would wait for the - * engine to create them, but for EXR file we need to know in - * advance. */ - ListBase templates; - render_result_get_pass_templates(engine, re, rl, &templates); - - /* Create render passes requested by engine. Only this part is - * mutex locked to avoid deadlock with Python GIL. */ - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - LISTBASE_FOREACH (RenderPass *, pass, &templates) { - RE_create_render_pass( - re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL); - } - BLI_rw_mutex_unlock(&re->resultmutex); - - BLI_freelistN(&templates); - - /* Open EXR file for writing. */ - render_result_exr_file_path(re->scene, rl->name, rr->sample_nr, str); - printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str); - IMB_exrtile_begin_write(rl->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party); - } - } -} - -/* end write of exr tile file, read back first sample */ -void render_result_exr_file_end(Render *re, RenderEngine *engine) -{ - /* Preserve stamp data. */ - struct StampData *stamp_data = re->result->stamp_data; - re->result->stamp_data = NULL; - - /* Close EXR files. */ - for (RenderResult *rr = re->result; rr; rr = rr->next) { - LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) { - IMB_exr_close(rl->exrhandle); - rl->exrhandle = NULL; - } - - rr->do_exr_tile = false; - } - - /* Create new render result in memory instead of on disk. */ - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - render_result_free_list(&re->fullresult, re->result); - re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); - re->result->stamp_data = stamp_data; - render_result_passes_allocated_ensure(re->result); - BLI_rw_mutex_unlock(&re->resultmutex); - - LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) { - /* Get passes needed by engine. */ - ListBase templates; - render_result_get_pass_templates(engine, re, rl, &templates); - - /* Create render passes requested by engine. Only this part is - * mutex locked to avoid deadlock with Python GIL. */ - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - LISTBASE_FOREACH (RenderPass *, pass, &templates) { - RE_create_render_pass(re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL); - } - - BLI_freelistN(&templates); - - /* Render passes contents from file. */ - char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = ""; - render_result_exr_file_path(re->scene, rl->name, 0, str); - printf("read exr tmp file: %s\n", str); - - if (!render_result_exr_file_read_path(re->result, rl, str)) { - printf("cannot read: %s\n", str); - } - BLI_rw_mutex_unlock(&re->resultmutex); - } -} - -/* save part into exr file */ -void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart, const char *viewname) -{ - for (; rr && rrpart; rr = rr->next, rrpart = rrpart->next) { - save_render_result_tile(rr, rrpart, viewname); - } -} - -/* path to temporary exr file */ -void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath) -{ - char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100]; - const char *fi = BLI_path_basename(BKE_main_blendfile_path_from_global()); - - if (sample == 0) { - BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname); - } - else { - BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample); - } - - /* Make name safe for paths, see T43275. */ - BLI_filename_make_safe(name); - - BLI_join_dirfile(filepath, FILE_MAX, BKE_tempdir_session(), name); -} - /* called for reading temp files, and for external engines */ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, @@ -1416,7 +1179,7 @@ bool render_result_exr_file_cache_read(Render *re) char *root = U.render_cachedir; RE_FreeRenderResult(re->result); - re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); /* First try cache. */ render_result_exr_file_cache_path(re->scene, root, str); diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h index 1fc64a4ea97..4145bb3b8ab 100644 --- a/source/blender/render/intern/render_result.h +++ b/source/blender/render/intern/render_result.h @@ -25,9 +25,6 @@ #define PASS_VECTOR_MAX 10000.0f -#define RR_USE_MEM 0 -#define RR_USE_EXR 1 - #define RR_ALL_LAYERS NULL #define RR_ALL_VIEWS NULL @@ -51,7 +48,6 @@ extern "C" { struct RenderResult *render_result_new(struct Render *re, struct rcti *partrct, - int savebuffers, const char *layername, const char *viewname); @@ -81,12 +77,6 @@ void render_result_free_list(struct ListBase *lb, struct RenderResult *rr); void render_result_single_layer_begin(struct Render *re); void render_result_single_layer_end(struct Render *re); -/* EXR Tile File Render */ - -void render_result_save_empty_result_tiles(struct Render *re); -void render_result_exr_file_begin(struct Render *re, struct RenderEngine *engine); -void render_result_exr_file_end(struct Render *re, struct RenderEngine *engine); - /* render pass wrapper for gpencil */ struct RenderPass *render_layer_add_pass(struct RenderResult *rr, struct RenderLayer *rl, @@ -95,14 +85,6 @@ struct RenderPass *render_layer_add_pass(struct RenderResult *rr, const char *viewname, const char *chan_id); -void render_result_exr_file_merge(struct RenderResult *rr, - struct RenderResult *rrpart, - const char *viewname); - -void render_result_exr_file_path(struct Scene *scene, - const char *layname, - int sample, - char *filepath); int render_result_exr_file_read_path(struct RenderResult *rr, struct RenderLayer *rl_single, const char *filepath); diff --git a/source/blender/render/intern/render_types.h b/source/blender/render/intern/render_types.h index d2d2b499495..ca4f72350e1 100644 --- a/source/blender/render/intern/render_types.h +++ b/source/blender/render/intern/render_types.h @@ -47,30 +47,10 @@ struct ReportList; extern "C" { #endif -/* this is handed over to threaded hiding/passes/shading engine */ -typedef struct RenderPart { - struct RenderPart *next, *prev; - - RenderResult *result; /* result of part rendering */ - ListBase fullresult; /* optional full sample buffers */ - - rcti disprect; /* part coordinates within total picture */ - int rectx, recty; /* the size */ - int nr; /* nr is partnr */ - short status; -} RenderPart; - typedef struct HighlightedTile { rcti rect; } HighlightedTile; -enum { - /* PART_STATUS_NONE = 0, */ /* UNUSED */ - PART_STATUS_IN_PROGRESS = 1, - PART_STATUS_RENDERED = 2, - PART_STATUS_MERGED = 3, -}; - /* controls state of render, everything that's read-only during render stage */ struct Render { struct Render *next, *prev; @@ -91,6 +71,9 @@ struct Render { * to not conflict with writes, so no lock used for that */ ThreadRWMutex resultmutex; + /* Guard for drawing render result using engine's `draw()` callback. */ + ThreadMutex engine_draw_mutex; + /** Window size, display rect, viewplane. * \note Buffer width and height with percentage applied * without border & crop. convert to long before multiplying together to avoid overflow. */ @@ -101,10 +84,6 @@ struct Render { /* final picture width and height (within disprect) */ int rectx, recty; - /* real maximum size of parts after correction for minimum - * partx*xparts can be larger than rectx, in that case last part is smaller */ - int partx, party; - /* Camera transform, only used by Freestyle. */ float winmat[4][4]; @@ -120,9 +99,6 @@ struct Render { int active_view_layer; struct Object *camera_override; - ThreadRWMutex partsmutex; - struct GHash *parts; - ThreadMutex highlighted_tiles_mutex; struct GSet *highlighted_tiles; diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 887aed7ffc7..8baf4a0e013 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -2426,10 +2426,15 @@ void wm_window_IME_end(wmWindow *win) void *WM_opengl_context_create(void) { - /* On Windows there is a problem creating contexts that share lists - * from one context that is current in another thread. - * So we should call this function only on the main thread. - */ + /* On Windows there is a problem creating contexts that share resources (almost any object, + * including legacy display lists, but also textures) with a context which is current in another + * thread. This is a documented and behavior of both `::wglCreateContextAttribsARB()` and + * `::wglShareLists()`. + * + * Other platforms might successfully share resources from context which is active somewhere + * else, but to keep our code behave the same on all platform we expect contexts to only be + * created from the main thread. */ + BLI_assert(BLI_thread_is_main()); BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get()); |