Merge branch 'master' into temp_bmesh_multires
This commit is contained in:
commit
8aac19cab5
|
@ -1,2 +1,2 @@
|
|||
Sphinx==3.5.1
|
||||
sphinx_rtd_theme==0.5.1
|
||||
Sphinx==3.5.3
|
||||
sphinx_rtd_theme==0.5.2
|
||||
|
|
|
@ -41,6 +41,9 @@ class AddPresetIntegrator(AddPresetBase, Operator):
|
|||
"cycles.caustics_reflective",
|
||||
"cycles.caustics_refractive",
|
||||
"cycles.blur_glossy"
|
||||
"cycles.use_fast_gi"
|
||||
"cycles.ao_bounces"
|
||||
"cycles.ao_bounces_render"
|
||||
]
|
||||
|
||||
preset_subdir = "cycles/integrator"
|
||||
|
|
|
@ -801,17 +801,22 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||
items=enum_texture_limit
|
||||
)
|
||||
|
||||
use_fast_gi: BoolProperty(
|
||||
name="Fast GI Approximation",
|
||||
description="Approximate diffuse indirect light with background tinted ambient occlusion. This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
|
||||
default=False,
|
||||
)
|
||||
ao_bounces: IntProperty(
|
||||
name="AO Bounces",
|
||||
default=0,
|
||||
description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
|
||||
default=1,
|
||||
description="After this number of light bounces, use approximate global illumination. 0 disables this feature",
|
||||
min=0, max=1024,
|
||||
)
|
||||
|
||||
ao_bounces_render: IntProperty(
|
||||
name="AO Bounces Render",
|
||||
default=0,
|
||||
description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
|
||||
default=1,
|
||||
description="After this number of light bounces, use approximate global illumination. 0 disables this feature",
|
||||
min=0, max=1024,
|
||||
)
|
||||
|
||||
|
|
|
@ -526,6 +526,35 @@ class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel):
|
|||
col.prop(cscene, "caustics_refractive", text="Refractive")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_light_paths_fast_gi(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Fast GI Approximation"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_parent_id = "CYCLES_RENDER_PT_light_paths"
|
||||
|
||||
def draw_header(self, context):
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
|
||||
self.layout.prop(cscene, "use_fast_gi", text="")
|
||||
|
||||
def draw(self, context):
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
world = scene.world
|
||||
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(cscene, "ao_bounces", text="Viewport Bounces")
|
||||
col.prop(cscene, "ao_bounces_render", text="Render Bounces")
|
||||
|
||||
if world:
|
||||
light = world.light_settings
|
||||
layout.prop(light, "distance", text="AO Distance")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Motion Blur"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
@ -746,7 +775,7 @@ class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
|
|||
col = layout.column()
|
||||
|
||||
col.prop(rd, "use_save_buffers")
|
||||
col.prop(rd, "use_persistent_data", text="Persistent Images")
|
||||
col.prop(rd, "use_persistent_data", text="Persistent Data")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel):
|
||||
|
@ -2041,7 +2070,6 @@ class CYCLES_RENDER_PT_simplify_viewport(CyclesButtonsPanel, Panel):
|
|||
col.prop(rd, "simplify_subdivision", text="Max Subdivision")
|
||||
col.prop(rd, "simplify_child_particles", text="Child Particles")
|
||||
col.prop(cscene, "texture_limit", text="Texture Limit")
|
||||
col.prop(cscene, "ao_bounces", text="AO Bounces")
|
||||
col.prop(rd, "simplify_volumes", text="Volume Resolution")
|
||||
|
||||
|
||||
|
@ -2067,7 +2095,6 @@ class CYCLES_RENDER_PT_simplify_render(CyclesButtonsPanel, Panel):
|
|||
col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
|
||||
col.prop(rd, "simplify_child_particles_render", text="Child Particles")
|
||||
col.prop(cscene, "texture_limit_render", text="Texture Limit")
|
||||
col.prop(cscene, "ao_bounces_render", text="AO Bounces")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
|
||||
|
@ -2245,6 +2272,7 @@ classes = (
|
|||
CYCLES_RENDER_PT_light_paths_max_bounces,
|
||||
CYCLES_RENDER_PT_light_paths_clamping,
|
||||
CYCLES_RENDER_PT_light_paths_caustics,
|
||||
CYCLES_RENDER_PT_light_paths_fast_gi,
|
||||
CYCLES_RENDER_PT_volumes,
|
||||
CYCLES_RENDER_PT_subdivision,
|
||||
CYCLES_RENDER_PT_hair,
|
||||
|
|
|
@ -217,6 +217,15 @@ def do_versions(self):
|
|||
baov.name = caov.get("name", "AOV")
|
||||
baov.type = "COLOR" if caov.get("type", 1) == 1 else "VALUE"
|
||||
|
||||
if version <= (2, 93, 16):
|
||||
cscene = scene.cycles
|
||||
if scene.render.use_simplify and \
|
||||
(cscene.ao_bounces or cscene.ao_bounces_render):
|
||||
cscene.use_fast_gi = True
|
||||
else:
|
||||
cscene.ao_bounces = 1
|
||||
cscene.ao_bounces_render = 1
|
||||
|
||||
# Lamps
|
||||
for light in bpy.data.lights:
|
||||
if light.library not in libraries:
|
||||
|
|
|
@ -143,12 +143,6 @@ void BlenderSession::create_session()
|
|||
|
||||
session->scene = scene;
|
||||
|
||||
/* There is no single depsgraph to use for the entire render.
|
||||
* So we need to handle this differently.
|
||||
*
|
||||
* We could loop over the final render result render layers in pipeline and keep Cycles unaware
|
||||
* of multiple layers, or perhaps move syncing further down in the pipeline.
|
||||
*/
|
||||
/* create sync */
|
||||
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
|
||||
BL::Object b_camera_override(b_engine.camera_override());
|
||||
|
@ -213,7 +207,7 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
|
|||
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
|
||||
|
||||
if (scene->params.modified(scene_params) || session->params.modified(session_params) ||
|
||||
!scene_params.persistent_data) {
|
||||
!this->b_render.use_persistent_data()) {
|
||||
/* if scene or session parameters changed, it's easier to simply re-create
|
||||
* them rather than trying to distinguish which settings need to be updated
|
||||
*/
|
||||
|
@ -225,7 +219,6 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
|
|||
}
|
||||
|
||||
session->progress.reset();
|
||||
scene->reset();
|
||||
|
||||
session->tile_manager.set_tile_order(session_params.tile_order);
|
||||
|
||||
|
@ -234,12 +227,15 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
|
|||
*/
|
||||
session->stats.mem_peak = session->stats.mem_used;
|
||||
|
||||
/* There is no single depsgraph to use for the entire render.
|
||||
* See note on create_session().
|
||||
*/
|
||||
/* sync object should be re-created */
|
||||
delete sync;
|
||||
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
|
||||
if (is_new_session) {
|
||||
/* Sync object should be re-created for new scene. */
|
||||
delete sync;
|
||||
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
|
||||
}
|
||||
else {
|
||||
/* Sync recalculations to do just the required updates. */
|
||||
sync->sync_recalc(b_depsgraph, b_v3d);
|
||||
}
|
||||
|
||||
BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
|
||||
BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
|
||||
|
@ -598,18 +594,6 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
|
|||
/* clear callback */
|
||||
session->write_render_tile_cb = function_null;
|
||||
session->update_render_tile_cb = function_null;
|
||||
|
||||
/* TODO: find a way to clear this data for persistent data render */
|
||||
#if 0
|
||||
/* free all memory used (host and device), so we wouldn't leave render
|
||||
* engine with extra memory allocated
|
||||
*/
|
||||
|
||||
session->device_free();
|
||||
|
||||
delete sync;
|
||||
sync = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bake_pass_filter_get(const int pass_filter)
|
||||
|
|
|
@ -211,9 +211,11 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
|||
}
|
||||
}
|
||||
|
||||
BlenderViewportParameters new_viewport_parameters(b_v3d);
|
||||
if (viewport_parameters.modified(new_viewport_parameters)) {
|
||||
world_recalc = true;
|
||||
if (b_v3d) {
|
||||
BlenderViewportParameters new_viewport_parameters(b_v3d);
|
||||
if (viewport_parameters.modified(new_viewport_parameters)) {
|
||||
world_recalc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,7 +360,7 @@ void BlenderSync::sync_integrator()
|
|||
|
||||
integrator->set_adaptive_min_samples(adaptive_min_samples);
|
||||
|
||||
if (b_scene.render().use_simplify()) {
|
||||
if (get_boolean(cscene, "use_fast_gi")) {
|
||||
if (preview) {
|
||||
integrator->set_ao_bounces(get_int(cscene, "ao_bounces"));
|
||||
}
|
||||
|
@ -757,7 +759,6 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
|
|||
|
||||
SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
|
||||
{
|
||||
BL::RenderSettings r = b_scene.render();
|
||||
SceneParams params;
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
|
||||
|
@ -781,11 +782,6 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
|
|||
params.hair_shape = (CurveShapeType)get_enum(
|
||||
csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK);
|
||||
|
||||
if (background && params.shadingsystem != SHADINGSYSTEM_OSL)
|
||||
params.persistent_data = r.use_persistent_data();
|
||||
else
|
||||
params.persistent_data = false;
|
||||
|
||||
int texture_limit;
|
||||
if (background) {
|
||||
texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
|
||||
|
|
|
@ -179,7 +179,7 @@ void Scene::free_memory(bool final)
|
|||
|
||||
bake_manager->device_free(device, &dscene);
|
||||
|
||||
if (!params.persistent_data || final)
|
||||
if (final)
|
||||
image_manager->device_free(device);
|
||||
else
|
||||
image_manager->device_free_builtin(device);
|
||||
|
|
|
@ -178,7 +178,6 @@ class SceneParams {
|
|||
int num_bvh_time_steps;
|
||||
int hair_subdivisions;
|
||||
CurveShapeType hair_shape;
|
||||
bool persistent_data;
|
||||
int texture_limit;
|
||||
|
||||
bool background;
|
||||
|
@ -193,7 +192,6 @@ class SceneParams {
|
|||
num_bvh_time_steps = 0;
|
||||
hair_subdivisions = 3;
|
||||
hair_shape = CURVE_RIBBON;
|
||||
persistent_data = false;
|
||||
texture_limit = 0;
|
||||
background = true;
|
||||
}
|
||||
|
@ -206,7 +204,7 @@ class SceneParams {
|
|||
use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes &&
|
||||
num_bvh_time_steps == params.num_bvh_time_steps &&
|
||||
hair_subdivisions == params.hair_subdivisions && hair_shape == params.hair_shape &&
|
||||
persistent_data == params.persistent_data && texture_limit == params.texture_limit);
|
||||
texture_limit == params.texture_limit);
|
||||
}
|
||||
|
||||
int curve_subdivisions()
|
||||
|
@ -301,7 +299,7 @@ class Scene : public NodeOwner {
|
|||
* node array (e.g. Scene::geometry for Geometry nodes) and tag the appropriate
|
||||
* manager for an update.
|
||||
*/
|
||||
template<typename T, typename... Args> T *create_node(Args &&... args)
|
||||
template<typename T, typename... Args> T *create_node(Args &&...args)
|
||||
{
|
||||
T *node = new T(args...);
|
||||
node->set_owner(this);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import bpy
|
||||
cycles = bpy.context.scene.cycles
|
||||
|
||||
cycles.max_bounces = 12
|
||||
cycles.caustics_reflective = True
|
||||
cycles.caustics_refractive = True
|
||||
cycles.diffuse_bounces = 4
|
||||
cycles.glossy_bounces = 4
|
||||
cycles.transmission_bounces = 12
|
||||
cycles.volume_bounces = 0
|
||||
cycles.transparent_max_bounces = 8
|
||||
cycles.use_fast_gi = False
|
||||
cycles.ao_bounces = 1
|
||||
cycles.ao_bounces_render = 1
|
|
@ -9,3 +9,6 @@ cycles.glossy_bounces = 1
|
|||
cycles.transmission_bounces = 2
|
||||
cycles.volume_bounces = 0
|
||||
cycles.transparent_max_bounces = 8
|
||||
cycles.use_fast_gi = False
|
||||
cycles.ao_bounces = 1
|
||||
cycles.ao_bounces_render = 1
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import bpy
|
||||
cycles = bpy.context.scene.cycles
|
||||
|
||||
cycles.max_bounces = 8
|
||||
cycles.caustics_reflective = False
|
||||
cycles.caustics_refractive = False
|
||||
cycles.diffuse_bounces = 1
|
||||
cycles.glossy_bounces = 4
|
||||
cycles.transmission_bounces = 8
|
||||
cycles.volume_bounces = 2
|
||||
cycles.transparent_max_bounces = 8
|
||||
cycles.use_fast_gi = True
|
||||
cycles.ao_bounces = 2
|
||||
cycles.ao_bounces_render = 2
|
|
@ -1,11 +1,14 @@
|
|||
import bpy
|
||||
cycles = bpy.context.scene.cycles
|
||||
|
||||
cycles.max_bounces = 128
|
||||
cycles.max_bounces = 32
|
||||
cycles.caustics_reflective = True
|
||||
cycles.caustics_refractive = True
|
||||
cycles.diffuse_bounces = 128
|
||||
cycles.glossy_bounces = 128
|
||||
cycles.transmission_bounces = 128
|
||||
cycles.volume_bounces = 128
|
||||
cycles.transparent_max_bounces = 128
|
||||
cycles.diffuse_bounces = 32
|
||||
cycles.glossy_bounces = 32
|
||||
cycles.transmission_bounces = 32
|
||||
cycles.volume_bounces = 32
|
||||
cycles.transparent_max_bounces = 32
|
||||
cycles.use_fast_gi = False
|
||||
cycles.ao_bounces = 1
|
||||
cycles.ao_bounces_render = 1
|
||||
|
|
|
@ -7,5 +7,8 @@ cycles.caustics_refractive = False
|
|||
cycles.diffuse_bounces = 1
|
||||
cycles.glossy_bounces = 4
|
||||
cycles.transmission_bounces = 8
|
||||
cycles.volume_bounces = 2
|
||||
cycles.volume_bounces = 0
|
||||
cycles.transparent_max_bounces = 8
|
||||
cycles.use_fast_gi = False
|
||||
cycles.ao_bounces = 1
|
||||
cycles.ao_bounces_render = 1
|
||||
|
|
|
@ -39,7 +39,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 16
|
||||
#define BLENDER_FILE_SUBVERSION 17
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -2661,7 +2661,7 @@ static void scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain, bool on
|
|||
bmain, &scene->id, depsgraph, BKE_CB_EVT_DEPSGRAPH_UPDATE_POST);
|
||||
|
||||
/* It is possible that the custom callback modified scene and removed some IDs from the main
|
||||
* database. In this case DEG_ids_clear_recalc() will crash because it iterates over all IDs
|
||||
* database. In this case DEG_editors_update() will crash because it iterates over all IDs
|
||||
* which depsgraph was built for.
|
||||
*
|
||||
* The solution is to update relations prior to this call, avoiding access to freed IDs.
|
||||
|
@ -2674,9 +2674,7 @@ static void scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain, bool on
|
|||
DEG_graph_relations_update(depsgraph);
|
||||
}
|
||||
/* Inform editors about possible changes. */
|
||||
DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, false);
|
||||
/* Clear recalc flags. */
|
||||
DEG_ids_clear_recalc(bmain, depsgraph);
|
||||
DEG_editors_update(bmain, depsgraph, scene, view_layer, false);
|
||||
|
||||
/* If user callback did not tag anything for update we can skip second iteration.
|
||||
* Otherwise we update scene once again, but without running callbacks to bring
|
||||
|
@ -2737,14 +2735,12 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
|
|||
BKE_callback_exec_id_depsgraph(bmain, &scene->id, depsgraph, BKE_CB_EVT_FRAME_CHANGE_POST);
|
||||
|
||||
/* NOTE: Similar to this case in scene_graph_update_tagged(). Need to ensure that
|
||||
* DEG_ids_clear_recalc() doesn't access freed memory of possibly removed ID. */
|
||||
* DEG_editors_update() doesn't access freed memory of possibly removed ID. */
|
||||
DEG_graph_relations_update(depsgraph);
|
||||
}
|
||||
|
||||
/* Inform editors about possible changes. */
|
||||
DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, true);
|
||||
/* clear recalc flags */
|
||||
DEG_ids_clear_recalc(bmain, depsgraph);
|
||||
DEG_editors_update(bmain, depsgraph, scene, view_layer, true);
|
||||
|
||||
/* If user callback did not tag anything for update we can skip second iteration.
|
||||
* Otherwise we update scene once again, but without running callbacks to bring
|
||||
|
@ -3463,6 +3459,9 @@ static Depsgraph **scene_ensure_depsgraph_p(Main *bmain, Scene *scene, ViewLayer
|
|||
BLI_snprintf(name, sizeof(name), "%s :: %s", scene->id.name, view_layer->name);
|
||||
DEG_debug_name_set(*depsgraph_ptr, name);
|
||||
|
||||
/* These viewport depsgraphs communicate changes to the editors. */
|
||||
DEG_enable_editors_update(*depsgraph_ptr);
|
||||
|
||||
return depsgraph_ptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -337,10 +337,10 @@ bool _bli_array_iter_spiral_square(const void *arr_v,
|
|||
center[1] < arr_shape[1]);
|
||||
|
||||
const char *arr = arr_v;
|
||||
const int stride[2] = {arr_shape[1] * (int)elem_size, (int)elem_size};
|
||||
const int stride[2] = {arr_shape[0] * (int)elem_size, (int)elem_size};
|
||||
|
||||
/* Test center first. */
|
||||
int ofs[2] = {center[0] * stride[0], center[1] * stride[1]};
|
||||
int ofs[2] = {center[0] * stride[1], center[1] * stride[0]};
|
||||
if (test_fn(arr + ofs[0] + ofs[1], user_data)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -139,16 +139,20 @@ void DEG_graph_time_tag_update(struct Depsgraph *depsgraph);
|
|||
void DEG_graph_id_type_tag(struct Depsgraph *depsgraph, short id_type);
|
||||
void DEG_id_type_tag(struct Main *bmain, short id_type);
|
||||
|
||||
void DEG_ids_clear_recalc(struct Main *bmain, Depsgraph *depsgraph);
|
||||
/* Set a depsgraph to flush updates to editors. This would be done
|
||||
* for viewport depsgraphs, but not render or export depsgraph for example. */
|
||||
void DEG_enable_editors_update(struct Depsgraph *depsgraph);
|
||||
|
||||
/* Check if something was changed in the database and inform
|
||||
* editors about this.
|
||||
*/
|
||||
void DEG_ids_check_recalc(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer,
|
||||
bool time);
|
||||
/* Check if something was changed in the database and inform editors about this,
|
||||
* then clear recalc flags. */
|
||||
void DEG_editors_update(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer,
|
||||
bool time);
|
||||
|
||||
/* Clear recalc flags after editors or renderers have handled updates. */
|
||||
void DEG_ids_clear_recalc(Depsgraph *depsgraph);
|
||||
|
||||
/* ************************************************ */
|
||||
/* Evaluation Engine API */
|
||||
|
|
|
@ -70,7 +70,8 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati
|
|||
scene_cow(nullptr),
|
||||
is_active(false),
|
||||
is_evaluating(false),
|
||||
is_render_pipeline_depsgraph(false)
|
||||
is_render_pipeline_depsgraph(false),
|
||||
use_editors_update(false)
|
||||
{
|
||||
BLI_spin_init(&lock);
|
||||
memset(id_type_updated, 0, sizeof(id_type_updated));
|
||||
|
@ -285,7 +286,9 @@ Depsgraph *DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEval
|
|||
}
|
||||
|
||||
/* Replace the "owner" pointers (currently Main/Scene/ViewLayer) of this depsgraph.
|
||||
* Used during undo steps when we do want to re-use the old depsgraph data as much as possible. */
|
||||
* Used for:
|
||||
* - Undo steps when we do want to re-use the old depsgraph data as much as possible.
|
||||
* - Rendering where we want to re-use objects between different view layers. */
|
||||
void DEG_graph_replace_owners(struct Depsgraph *depsgraph,
|
||||
Main *bmain,
|
||||
Scene *scene,
|
||||
|
|
|
@ -161,6 +161,9 @@ struct Depsgraph {
|
|||
* does not need any bases. */
|
||||
bool is_render_pipeline_depsgraph;
|
||||
|
||||
/* Notify editors about changes to IDs in this depsgrpah. */
|
||||
bool use_editors_update;
|
||||
|
||||
/* Cached list of colliders/effectors for collections and the scene
|
||||
* created along with relations, for fast lookup during evaluation. */
|
||||
Map<const ID *, ListBase *> *physics_relations[DEG_PHYSICS_RELATIONS_NUM];
|
||||
|
|
|
@ -816,11 +816,22 @@ void DEG_on_visible_update(Main *bmain, const bool do_time)
|
|||
}
|
||||
}
|
||||
|
||||
void DEG_enable_editors_update(Depsgraph *depsgraph)
|
||||
{
|
||||
deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph;
|
||||
graph->use_editors_update = true;
|
||||
}
|
||||
|
||||
/* Check if something was changed in the database and inform
|
||||
* editors about this. */
|
||||
void DEG_ids_check_recalc(
|
||||
void DEG_editors_update(
|
||||
Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, bool time)
|
||||
{
|
||||
deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph;
|
||||
if (!graph->use_editors_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool updated = time || DEG_id_type_any_updated(depsgraph);
|
||||
|
||||
DEGEditorUpdateContext update_ctx = {nullptr};
|
||||
|
@ -829,6 +840,8 @@ void DEG_ids_check_recalc(
|
|||
update_ctx.scene = scene;
|
||||
update_ctx.view_layer = view_layer;
|
||||
deg::deg_editors_scene_update(&update_ctx, updated);
|
||||
|
||||
DEG_ids_clear_recalc(depsgraph);
|
||||
}
|
||||
|
||||
static void deg_graph_clear_id_recalc_flags(ID *id)
|
||||
|
@ -842,7 +855,7 @@ static void deg_graph_clear_id_recalc_flags(ID *id)
|
|||
/* XXX And what about scene's master collection here? */
|
||||
}
|
||||
|
||||
void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph)
|
||||
void DEG_ids_clear_recalc(Depsgraph *depsgraph)
|
||||
{
|
||||
deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
|
||||
/* TODO(sergey): Re-implement POST_UPDATE_HANDLER_WORKAROUND using entry_tags
|
||||
|
|
|
@ -206,7 +206,9 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd,
|
|||
else {
|
||||
const ViewDepths *depths = rv3d->depths;
|
||||
if (depths && ((uint)mval_i[0] < depths->w) && ((uint)mval_i[1] < depths->h)) {
|
||||
const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i);
|
||||
float depth_fl = 1.0f;
|
||||
ED_view3d_depth_read_cached(depths, mval_i, 0, &depth_fl);
|
||||
const double depth = (double)depth_fl;
|
||||
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
|
||||
if (ED_view3d_depth_unproject(region, mval_i, depth, r_location_world)) {
|
||||
is_location_world_set = true;
|
||||
|
|
|
@ -155,7 +155,10 @@ void ED_view3d_depth_override(struct Depsgraph *depsgraph,
|
|||
struct Object *obact,
|
||||
eV3DDepthOverrideMode mode,
|
||||
bool update_cache);
|
||||
float ED_view3d_depth_read_cached(const struct ViewContext *vc, const int mval[2]);
|
||||
bool ED_view3d_depth_read_cached(const ViewDepths *vd,
|
||||
const int mval[2],
|
||||
int margin,
|
||||
float *r_depth);
|
||||
bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
|
||||
const int mval[2],
|
||||
float r_normal[3]);
|
||||
|
|
|
@ -1865,28 +1865,30 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
|
|||
if (event->type == MOUSEMOVE || is_translate_init) {
|
||||
const ViewDepths *depths = xfd->vc.rv3d->depths;
|
||||
if (depths && ((uint)event->mval[0] < depths->w) && ((uint)event->mval[1] < depths->h)) {
|
||||
double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
|
||||
float depth_fl = 1.0f;
|
||||
ED_view3d_depth_read_cached(depths, event->mval, 0, &depth_fl);
|
||||
float location_world[3];
|
||||
if (depth == 1.0f) {
|
||||
if (depth_fl == 1.0f) {
|
||||
if (xfd->prev.is_depth_valid) {
|
||||
depth = (double)xfd->prev.depth;
|
||||
depth_fl = xfd->prev.depth;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_FAKE_DEPTH_INIT
|
||||
/* First time only. */
|
||||
if (depth == 1.0f) {
|
||||
if (depth_fl == 1.0f) {
|
||||
if (xfd->prev.is_depth_valid == false) {
|
||||
object_transform_axis_target_calc_depth_init(xfd, event->mval);
|
||||
if (xfd->prev.is_depth_valid) {
|
||||
depth = (double)xfd->prev.depth;
|
||||
depth_fl = xfd->prev.depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
double depth = (double)depth_fl;
|
||||
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
|
||||
xfd->prev.depth = depth;
|
||||
xfd->prev.depth = depth_fl;
|
||||
xfd->prev.is_depth_valid = true;
|
||||
if (ED_view3d_depth_unproject(region, event->mval, depth, location_world)) {
|
||||
if (is_translate) {
|
||||
|
|
|
@ -188,7 +188,7 @@ void ED_render_engine_changed(Main *bmain, const bool update_scene_data)
|
|||
ED_render_engine_area_exit(bmain, area);
|
||||
}
|
||||
}
|
||||
RE_FreePersistentData();
|
||||
RE_FreePersistentData(NULL);
|
||||
/* Inform all render engines and draw managers. */
|
||||
DEGEditorUpdateContext update_ctx = {NULL};
|
||||
update_ctx.bmain = bmain;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_array_utils.h"
|
||||
#include "BLI_bitmap_draw_2d.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
|
@ -1629,19 +1630,48 @@ bool ED_view3d_camera_to_view_selected(struct Main *bmain,
|
|||
/** \name Depth Buffer Utilities
|
||||
* \{ */
|
||||
|
||||
float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
|
||||
static bool depth_read_test_fn(const void *value, void *userdata)
|
||||
{
|
||||
ViewDepths *vd = vc->rv3d->depths;
|
||||
float *r_depth = userdata;
|
||||
float depth = *(float *)value;
|
||||
if (depth < *r_depth) {
|
||||
*r_depth = depth;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ED_view3d_depth_read_cached(const ViewDepths *vd,
|
||||
const int mval[2],
|
||||
int margin,
|
||||
float *r_depth)
|
||||
{
|
||||
if (!vd || !vd->depths) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = mval[0];
|
||||
int y = mval[1];
|
||||
if (x < 0 || y < 0 || x >= vd->w || y >= vd->h) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
|
||||
return vd->depths[y * vd->w + x];
|
||||
float depth = 1.0f;
|
||||
if (margin) {
|
||||
/* TODO: No need to go spiral. */
|
||||
int shape[2] = {vd->w, vd->h};
|
||||
BLI_array_iter_spiral_square(vd->depths, shape, mval, depth_read_test_fn, &depth);
|
||||
}
|
||||
else {
|
||||
depth = vd->depths[y * vd->w + x];
|
||||
}
|
||||
|
||||
BLI_assert(1.0 <= vd->depth_range[1]);
|
||||
return 1.0f;
|
||||
if (depth != 1.0f) {
|
||||
*r_depth = depth;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
|
||||
|
@ -1662,7 +1692,9 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
|
|||
for (int y = 0; y < 2; y++) {
|
||||
const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
|
||||
|
||||
const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
|
||||
float depth_fl = 1.0f;
|
||||
ED_view3d_depth_read_cached(depths, mval_ofs, 0, &depth_fl);
|
||||
const double depth = (double)depth_fl;
|
||||
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
|
||||
if (ED_view3d_depth_unproject(region, mval_ofs, depth, coords[i])) {
|
||||
depths_valid[i] = true;
|
||||
|
|
|
@ -298,13 +298,13 @@ static void rna_RenderEngine_unregister(Main *bmain, StructRNA *type)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Stop all renders in case we were using this one. */
|
||||
ED_render_engine_changed(bmain, false);
|
||||
RE_FreeAllPersistentData();
|
||||
|
||||
RNA_struct_free_extension(type, &et->rna_ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
BLI_freelinkN(&R_engines, et);
|
||||
|
||||
/* Stop all renders in case we were using this one. */
|
||||
ED_render_engine_changed(bmain, false);
|
||||
}
|
||||
|
||||
static StructRNA *rna_RenderEngine_register(Main *bmain,
|
||||
|
|
|
@ -1896,10 +1896,10 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain),
|
|||
Scene *UNUSED(scene),
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
Scene *sce = (Scene *)ptr->owner_id;
|
||||
Scene *scene = (Scene *)ptr->owner_id;
|
||||
|
||||
if (!(sce->r.mode & R_PERSISTENT_DATA)) {
|
||||
RE_FreePersistentData();
|
||||
if (!(scene->r.mode & R_PERSISTENT_DATA)) {
|
||||
RE_FreePersistentData(scene);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6606,8 +6606,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
|
|||
/* persistent data */
|
||||
prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Persistent Data", "Keep render data around for faster re-renders");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Persistent Data",
|
||||
"Keep render data around for faster re-renders and animation renders, "
|
||||
"at the cost of increased memory usage");
|
||||
RNA_def_property_update(prop, 0, "rna_Scene_use_persistent_data_update");
|
||||
|
||||
/* Freestyle line thickness options */
|
||||
|
|
|
@ -112,18 +112,6 @@ static bool rna_Screen_fullscreen_get(PointerRNA *ptr)
|
|||
return (screen->state == SCREENMAXIMIZED);
|
||||
}
|
||||
|
||||
/* UI compatible list: should not be needed, but for now we need to keep EMPTY
|
||||
* at least in the static version of this enum for python scripts. */
|
||||
static const EnumPropertyItem *rna_Area_type_itemf(bContext *UNUSED(C),
|
||||
PointerRNA *UNUSED(ptr),
|
||||
PropertyRNA *UNUSED(prop),
|
||||
bool *r_free)
|
||||
{
|
||||
/* +1 to skip SPACE_EMPTY */
|
||||
*r_free = false;
|
||||
return rna_enum_space_type_items + 1;
|
||||
}
|
||||
|
||||
static int rna_Area_type_get(PointerRNA *ptr)
|
||||
{
|
||||
ScrArea *area = (ScrArea *)ptr->data;
|
||||
|
@ -142,6 +130,11 @@ static void rna_Area_type_set(PointerRNA *ptr, int value)
|
|||
}
|
||||
|
||||
ScrArea *area = (ScrArea *)ptr->data;
|
||||
/* Empty areas are locked. */
|
||||
if ((value == SPACE_EMPTY) || (area->spacetype == SPACE_EMPTY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
area->butspacetype = value;
|
||||
}
|
||||
|
||||
|
@ -188,16 +181,20 @@ static void rna_Area_type_update(bContext *C, PointerRNA *ptr)
|
|||
}
|
||||
|
||||
static const EnumPropertyItem *rna_Area_ui_type_itemf(bContext *C,
|
||||
PointerRNA *UNUSED(ptr),
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *UNUSED(prop),
|
||||
bool *r_free)
|
||||
{
|
||||
EnumPropertyItem *item = NULL;
|
||||
int totitem = 0;
|
||||
|
||||
/* +1 to skip SPACE_EMPTY */
|
||||
for (const EnumPropertyItem *item_from = rna_enum_space_type_items + 1; item_from->identifier;
|
||||
item_from++) {
|
||||
ScrArea *area = (ScrArea *)ptr->data;
|
||||
const EnumPropertyItem *item_from = rna_enum_space_type_items;
|
||||
if (area->spacetype != SPACE_EMPTY) {
|
||||
item_from += 1; /* +1 to skip SPACE_EMPTY */
|
||||
}
|
||||
|
||||
for (; item_from->identifier; item_from++) {
|
||||
if (ELEM(item_from->value, SPACE_TOPBAR, SPACE_STATUSBAR)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -224,6 +221,10 @@ static const EnumPropertyItem *rna_Area_ui_type_itemf(bContext *C,
|
|||
static int rna_Area_ui_type_get(PointerRNA *ptr)
|
||||
{
|
||||
ScrArea *area = ptr->data;
|
||||
/* This is for the Python API which may inspect empty areas. */
|
||||
if (UNLIKELY(area->spacetype == SPACE_EMPTY)) {
|
||||
return SPACE_EMPTY;
|
||||
}
|
||||
const int area_type = rna_Area_type_get(ptr);
|
||||
const bool area_changing = area->butspacetype != SPACE_EMPTY;
|
||||
int value = area_type << 16;
|
||||
|
@ -252,6 +253,10 @@ static void rna_Area_ui_type_set(PointerRNA *ptr, int value)
|
|||
{
|
||||
ScrArea *area = ptr->data;
|
||||
const int space_type = value >> 16;
|
||||
/* Empty areas are locked. */
|
||||
if ((space_type == SPACE_EMPTY) || (area->spacetype == SPACE_EMPTY)) {
|
||||
return;
|
||||
}
|
||||
SpaceType *st = BKE_spacetype_from_id(space_type);
|
||||
|
||||
rna_Area_type_set(ptr, space_type);
|
||||
|
@ -380,12 +385,17 @@ static void rna_def_area(BlenderRNA *brna)
|
|||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", HEADER_NO_PULLDOWN);
|
||||
RNA_def_property_ui_text(prop, "Show Menus", "Show menus in the header");
|
||||
|
||||
/* Note on space type use of #SPACE_EMPTY, this is not visible to the user,
|
||||
* and script authors should be able to assign this value, however the value may be set
|
||||
* and needs to be read back by script authors.
|
||||
*
|
||||
* This happens when an area is full-screen (when #ScrArea.full is set).
|
||||
* in this case reading the empty value is needed, but it should never be set, see: T87187. */
|
||||
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "spacetype");
|
||||
RNA_def_property_enum_items(prop, rna_enum_space_type_items);
|
||||
RNA_def_property_enum_default(prop, SPACE_VIEW3D);
|
||||
RNA_def_property_enum_funcs(
|
||||
prop, "rna_Area_type_get", "rna_Area_type_set", "rna_Area_type_itemf");
|
||||
RNA_def_property_enum_funcs(prop, "rna_Area_type_get", "rna_Area_type_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Editor Type", "Current editor type for this area");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
|
|
|
@ -224,6 +224,8 @@ void RE_engine_register_pass(struct RenderEngine *engine,
|
|||
const char *chanid,
|
||||
eNodeSocketDatatype type);
|
||||
|
||||
bool RE_engine_use_persistent_data(struct RenderEngine *engine);
|
||||
|
||||
/* Engine Types */
|
||||
|
||||
void RE_engines_init(void);
|
||||
|
|
|
@ -184,14 +184,14 @@ void RE_InitRenderCB(struct Render *re);
|
|||
void RE_FreeRender(struct Render *re);
|
||||
/* only called on exit */
|
||||
void RE_FreeAllRender(void);
|
||||
/* Free memory used by persistent data.
|
||||
* Invoked when loading new file.
|
||||
*/
|
||||
void RE_FreeAllPersistentData(void);
|
||||
/* only call on file load */
|
||||
|
||||
/* On file load, free render results. */
|
||||
void RE_FreeAllRenderResults(void);
|
||||
/* for external render engines that can keep persistent data */
|
||||
void RE_FreePersistentData(void);
|
||||
/* On file load or changes engines, free persistent render data.
|
||||
* Assumes no engines are currently rendering. */
|
||||
void RE_FreeAllPersistentData(void);
|
||||
/* Free persistent render data, optionally only for the given scene. */
|
||||
void RE_FreePersistentData(const Scene *scene);
|
||||
|
||||
/* get results and statistics */
|
||||
void RE_FreeRenderResult(struct RenderResult *rr);
|
||||
|
|
|
@ -140,6 +140,27 @@ RenderEngine *RE_engine_create(RenderEngineType *type)
|
|||
return engine;
|
||||
}
|
||||
|
||||
static void engine_depsgraph_free(RenderEngine *engine)
|
||||
{
|
||||
if (engine->depsgraph) {
|
||||
/* Need GPU context since this might free GPU buffers. This function can
|
||||
* only be called from a render thread. We do not currently support
|
||||
* persistent data with GPU contexts for that reason. */
|
||||
const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
|
||||
if (use_gpu_context) {
|
||||
BLI_assert(!BLI_thread_is_main());
|
||||
DRW_render_context_enable(engine->re);
|
||||
}
|
||||
|
||||
DEG_graph_free(engine->depsgraph);
|
||||
engine->depsgraph = NULL;
|
||||
|
||||
if (use_gpu_context) {
|
||||
DRW_render_context_disable(engine->re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RE_engine_free(RenderEngine *engine)
|
||||
{
|
||||
#ifdef WITH_PYTHON
|
||||
|
@ -148,6 +169,8 @@ void RE_engine_free(RenderEngine *engine)
|
|||
}
|
||||
#endif
|
||||
|
||||
engine_depsgraph_free(engine);
|
||||
|
||||
BLI_mutex_end(&engine->update_render_passes_mutex);
|
||||
|
||||
MEM_freeN(engine);
|
||||
|
@ -598,34 +621,94 @@ RenderData *RE_engine_get_render_data(Render *re)
|
|||
return &re->r;
|
||||
}
|
||||
|
||||
bool RE_engine_use_persistent_data(RenderEngine *engine)
|
||||
{
|
||||
/* See engine_depsgraph_free() for why preserving the depsgraph for
|
||||
* re-renders is not supported with GPU contexts. */
|
||||
return (engine->re->r.mode & R_PERSISTENT_DATA) && !(engine->type->flag & RE_USE_GPU_CONTEXT);
|
||||
}
|
||||
|
||||
static bool engine_keep_depsgraph(RenderEngine *engine)
|
||||
{
|
||||
/* For persistent data or GPU engines like Eevee, reuse the depsgraph between
|
||||
* view layers and animation frames. For renderers like Cycles that create
|
||||
* their own copy of the scene, persistent data must be explicitly enabled to
|
||||
* keep memory usage low by default. */
|
||||
return (engine->re->r.mode & R_PERSISTENT_DATA) || (engine->type->flag & RE_USE_GPU_CONTEXT);
|
||||
}
|
||||
|
||||
/* Depsgraph */
|
||||
static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
|
||||
{
|
||||
Main *bmain = engine->re->main;
|
||||
Scene *scene = engine->re->scene;
|
||||
bool reuse_depsgraph = false;
|
||||
|
||||
engine->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
|
||||
DEG_debug_name_set(engine->depsgraph, "RENDER");
|
||||
/* Reuse depsgraph from persistent data if possible. */
|
||||
if (engine->depsgraph) {
|
||||
if (DEG_get_bmain(engine->depsgraph) != bmain ||
|
||||
DEG_get_input_scene(engine->depsgraph) != scene) {
|
||||
/* If bmain or scene changes, we need a completely new graph. */
|
||||
engine_depsgraph_free(engine);
|
||||
}
|
||||
else if (DEG_get_input_view_layer(engine->depsgraph) != view_layer) {
|
||||
/* If only view layer changed, reuse depsgraph in the hope of reusing
|
||||
* objects shared between view layers. */
|
||||
DEG_graph_replace_owners(engine->depsgraph, bmain, scene, view_layer);
|
||||
DEG_graph_tag_relations_update(engine->depsgraph);
|
||||
}
|
||||
|
||||
reuse_depsgraph = true;
|
||||
}
|
||||
|
||||
if (!engine->depsgraph) {
|
||||
/* Ensure we only use persistent data for one scene / view layer at a time,
|
||||
* to avoid excessive memory usage. */
|
||||
RE_FreePersistentData(NULL);
|
||||
|
||||
/* Create new depsgraph if not cached with persistent data. */
|
||||
engine->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
|
||||
DEG_debug_name_set(engine->depsgraph, "RENDER");
|
||||
}
|
||||
|
||||
if (engine->re->r.scemode & R_BUTS_PREVIEW) {
|
||||
/* Update for preview render. */
|
||||
Depsgraph *depsgraph = engine->depsgraph;
|
||||
DEG_graph_relations_update(depsgraph);
|
||||
|
||||
/* Need GPU context since this might free GPU buffers. */
|
||||
const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT) && reuse_depsgraph;
|
||||
if (use_gpu_context) {
|
||||
DRW_render_context_enable(engine->re);
|
||||
}
|
||||
|
||||
DEG_evaluate_on_framechange(depsgraph, CFRA);
|
||||
DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, true);
|
||||
DEG_ids_clear_recalc(bmain, depsgraph);
|
||||
|
||||
if (use_gpu_context) {
|
||||
DRW_render_context_disable(engine->re);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Go through update with full Python callbacks for regular render. */
|
||||
BKE_scene_graph_update_for_newframe(engine->depsgraph);
|
||||
}
|
||||
|
||||
engine->has_grease_pencil = DRW_render_check_grease_pencil(engine->depsgraph);
|
||||
}
|
||||
|
||||
static void engine_depsgraph_free(RenderEngine *engine)
|
||||
static void engine_depsgraph_exit(RenderEngine *engine)
|
||||
{
|
||||
DEG_graph_free(engine->depsgraph);
|
||||
|
||||
engine->depsgraph = NULL;
|
||||
if (engine->depsgraph) {
|
||||
if (engine_keep_depsgraph(engine)) {
|
||||
/* Clear recalc flags since the engine should have handled the updates for the currently
|
||||
* rendered framed by now. */
|
||||
DEG_ids_clear_recalc(engine->depsgraph);
|
||||
}
|
||||
else {
|
||||
/* Free immediately to save memory. */
|
||||
engine_depsgraph_free(engine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
|
||||
|
@ -670,7 +753,6 @@ bool RE_bake_engine(Render *re,
|
|||
{
|
||||
RenderEngineType *type = RE_engines_find(re->r.engine);
|
||||
RenderEngine *engine;
|
||||
bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
|
||||
|
||||
/* set render info */
|
||||
re->i.cfra = re->scene->r.cfra;
|
||||
|
@ -729,13 +811,13 @@ bool RE_bake_engine(Render *re,
|
|||
engine->tile_y = 0;
|
||||
engine->flag &= ~RE_ENGINE_RENDERING;
|
||||
|
||||
/* Free depsgraph outside of parts mutex lock, since this locks OpenGL context
|
||||
* while the 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 becomes zero if user changed active render engine during render */
|
||||
if (!persistent_data || !re->engine) {
|
||||
RE_engine_free(engine);
|
||||
re->engine = NULL;
|
||||
}
|
||||
RE_engine_free(engine);
|
||||
re->engine = NULL;
|
||||
|
||||
RE_parts_free(re);
|
||||
BLI_rw_mutex_unlock(&re->partsmutex);
|
||||
|
@ -778,13 +860,14 @@ static void engine_render_view_layer(Render *re,
|
|||
|
||||
/* Perform render with engine. */
|
||||
if (use_engine) {
|
||||
if (engine->type->flag & RE_USE_GPU_CONTEXT) {
|
||||
const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
|
||||
if (use_gpu_context) {
|
||||
DRW_render_context_enable(engine->re);
|
||||
}
|
||||
|
||||
engine->type->render(engine, engine->depsgraph);
|
||||
|
||||
if (engine->type->flag & RE_USE_GPU_CONTEXT) {
|
||||
if (use_gpu_context) {
|
||||
DRW_render_context_disable(engine->re);
|
||||
}
|
||||
}
|
||||
|
@ -800,13 +883,12 @@ static void engine_render_view_layer(Render *re,
|
|||
}
|
||||
|
||||
/* Free dependency graph, if engine has not done it already. */
|
||||
engine_depsgraph_free(engine);
|
||||
engine_depsgraph_exit(engine);
|
||||
}
|
||||
|
||||
bool RE_engine_render(Render *re, bool do_all)
|
||||
{
|
||||
RenderEngineType *type = RE_engines_find(re->r.engine);
|
||||
bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
|
||||
|
||||
/* verify if we can render */
|
||||
if (!type->render) {
|
||||
|
@ -953,7 +1035,13 @@ bool RE_engine_render(Render *re, bool do_all)
|
|||
}
|
||||
|
||||
/* re->engine becomes zero if user changed active render engine during render */
|
||||
if (!persistent_data || !re->engine) {
|
||||
if (!engine_keep_depsgraph(engine) || !re->engine) {
|
||||
/* Free depsgraph outside of parts mutex lock, since this locks OpenGL context
|
||||
* while the 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;
|
||||
}
|
||||
|
@ -1023,9 +1111,8 @@ void RE_engine_free_blender_memory(RenderEngine *engine)
|
|||
*
|
||||
* TODO(sergey): Find better solution for this.
|
||||
*/
|
||||
if (engine->has_grease_pencil) {
|
||||
if (engine->has_grease_pencil || engine_keep_depsgraph(engine)) {
|
||||
return;
|
||||
}
|
||||
DEG_graph_free(engine->depsgraph);
|
||||
engine->depsgraph = NULL;
|
||||
engine_depsgraph_free(engine);
|
||||
}
|
||||
|
|
|
@ -662,17 +662,6 @@ void RE_FreeAllRender(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void RE_FreeAllPersistentData(void)
|
||||
{
|
||||
Render *re;
|
||||
for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
|
||||
if ((re->r.mode & R_PERSISTENT_DATA) != 0 && re->engine != NULL) {
|
||||
RE_engine_free(re->engine);
|
||||
re->engine = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* on file load, free all re */
|
||||
void RE_FreeAllRenderResults(void)
|
||||
{
|
||||
|
@ -687,23 +676,43 @@ void RE_FreeAllRenderResults(void)
|
|||
}
|
||||
}
|
||||
|
||||
void RE_FreePersistentData(void)
|
||||
void RE_FreeAllPersistentData(void)
|
||||
{
|
||||
Render *re;
|
||||
|
||||
/* render engines can be kept around for quick re-render, this clears all */
|
||||
for (re = RenderGlobal.renderlist.first; re; re = re->next) {
|
||||
if (re->engine) {
|
||||
/* if engine is currently rendering, just tag it to be freed when render is finished */
|
||||
if (!(re->engine->flag & RE_ENGINE_RENDERING)) {
|
||||
RE_engine_free(re->engine);
|
||||
}
|
||||
|
||||
for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
|
||||
if (re->engine != NULL) {
|
||||
BLI_assert(!(re->engine->flag & RE_ENGINE_RENDERING));
|
||||
RE_engine_free(re->engine);
|
||||
re->engine = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void re_free_persistent_data(Render *re)
|
||||
{
|
||||
/* If engine is currently rendering, just wait for it to be freed when it finishes rendering. */
|
||||
if (re->engine && !(re->engine->flag & RE_ENGINE_RENDERING)) {
|
||||
RE_engine_free(re->engine);
|
||||
re->engine = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RE_FreePersistentData(const Scene *scene)
|
||||
{
|
||||
/* Render engines can be kept around for quick re-render, this clears all or one scene. */
|
||||
if (scene) {
|
||||
Render *re = RE_GetSceneRender(scene);
|
||||
if (re) {
|
||||
re_free_persistent_data(re);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (Render *re = RenderGlobal.renderlist.first; re; re = re->next) {
|
||||
re_free_persistent_data(re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ********* initialize state ******** */
|
||||
|
||||
/* clear full sample and tile flags if needed */
|
||||
|
@ -2669,13 +2678,17 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
|
|||
|
||||
void RE_CleanAfterRender(Render *re)
|
||||
{
|
||||
/* Destroy the opengl context in the correct thread. */
|
||||
RE_gl_context_destroy(re);
|
||||
if (re->engine && !RE_engine_use_persistent_data(re->engine)) {
|
||||
RE_engine_free(re->engine);
|
||||
re->engine = NULL;
|
||||
}
|
||||
if (re->pipeline_depsgraph != NULL) {
|
||||
DEG_graph_free(re->pipeline_depsgraph);
|
||||
re->pipeline_depsgraph = NULL;
|
||||
re->pipeline_scene_eval = NULL;
|
||||
}
|
||||
re->pipeline_depsgraph = NULL;
|
||||
re->pipeline_scene_eval = NULL;
|
||||
/* Destroy the opengl context in the correct thread. */
|
||||
RE_gl_context_destroy(re);
|
||||
}
|
||||
|
||||
/* note; repeated win/disprect calc... solve that nicer, also in compo */
|
||||
|
|
Loading…
Reference in New Issue