diff --git a/source/blender/draw/engines/eevee_next/eevee_reflection_probes.cc b/source/blender/draw/engines/eevee_next/eevee_reflection_probes.cc index b0490ab4aaf..288cff416c3 100644 --- a/source/blender/draw/engines/eevee_next/eevee_reflection_probes.cc +++ b/source/blender/draw/engines/eevee_next/eevee_reflection_probes.cc @@ -155,7 +155,7 @@ ReflectionProbe &ReflectionProbeModule::find_or_insert(ObjectHandle &ob_handle, int subdivision_level) { ReflectionProbe &reflection_probe = probes_.lookup_or_add_cb( - ob_handle.object_key.hash_value, [this, subdivision_level]() { + ob_handle.object_key.hash(), [this, subdivision_level]() { ReflectionProbe probe; ReflectionProbeData probe_data = find_empty_reflection_probe_data(subdivision_level); diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc index 2d0901f2772..8285dbf4876 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.cc +++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc @@ -40,25 +40,24 @@ static void draw_data_init_cb(DrawData *dd) ObjectHandle &SyncModule::sync_object(Object *ob) { - DrawEngineType *owner = (DrawEngineType *)&DRW_engine_viewport_eevee_next_type; - DrawData *dd = DRW_drawdata_ensure( - (ID *)ob, owner, sizeof(eevee::ObjectHandle), draw_data_init_cb, nullptr); - ObjectHandle &eevee_dd = *reinterpret_cast(dd); + ObjectKey key(ob); - if (eevee_dd.object_key.ob == nullptr) { - ob = DEG_get_original_object(ob); - eevee_dd.object_key = ObjectKey(ob); - } + ObjectHandle &handle = ob_handles.lookup_or_add_cb(key, [&]() { + ObjectHandle new_handle; + new_handle.object_key = key; + new_handle.recalc = ID_RECALC_ALL; + return new_handle; + }); + + handle.recalc |= ob->id.recalc; const int recalc_flags = ID_RECALC_COPY_ON_WRITE | ID_RECALC_TRANSFORM | ID_RECALC_SHADING | ID_RECALC_GEOMETRY; - if ((eevee_dd.recalc & recalc_flags) != 0) { - /** WARNING: Some objects are always created "on the fly" (ie. Geometry Nodes volumes), - * so this causes to redraw the sample 1 forever. */ + if ((handle.recalc & recalc_flags) != 0) { inst_.sampling.reset(); } - return eevee_dd; + return handle; } WorldHandle &SyncModule::sync_world(::World *world) @@ -512,8 +511,8 @@ void foreach_hair_particle_handle(Object *ob, ObjectHandle ob_handle, HairHandle continue; } - ObjectHandle particle_sys_handle = {{nullptr}}; - particle_sys_handle.object_key = ObjectKey(ob_handle.object_key.ob, sub_key++); + ObjectHandle particle_sys_handle = ob_handle; + particle_sys_handle.object_key = ObjectKey(ob, sub_key++); particle_sys_handle.recalc = particle_sys->recalc; callback(particle_sys_handle, *md, *particle_sys); diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.hh b/source/blender/draw/engines/eevee_next/eevee_sync.hh index c813f5bc2ff..b1e4fafe341 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.hh +++ b/source/blender/draw/engines/eevee_next/eevee_sync.hh @@ -14,6 +14,7 @@ #include "BKE_duplilist.h" #include "BLI_ghash.h" #include "BLI_map.hh" +#include "DEG_depsgraph_query.hh" #include "DNA_object_types.h" #include "DRW_render.h" #include "GPU_material.h" @@ -31,87 +32,60 @@ class Instance; * Note that we get a unique key for each object component. * \{ */ -struct ObjectKey { +class ObjectKey { /** Hash value of the key. */ - uint64_t hash_value; + uint64_t hash_value_; /** Original Object or source object for duplis. */ - Object *ob; + Object *ob_; /** Original Parent object for duplis. */ - Object *parent; + Object *parent_; /** Dupli objects recursive unique identifier */ - int id[MAX_DUPLI_RECUR]; + int id_[MAX_DUPLI_RECUR]; /** Used for particle system hair. */ int sub_key_; -#ifdef DEBUG - char name[64]; -#endif - ObjectKey() : ob(nullptr), parent(nullptr){}; - ObjectKey(Object *ob_, Object *parent_, int id_[MAX_DUPLI_RECUR], int sub_key_ = 0) - : ob(ob_), parent(parent_), sub_key_(sub_key_) + public: + ObjectKey() = default; + + ObjectKey(Object *ob, int sub_key = 0) : sub_key_(sub_key) { - if (id_) { - memcpy(id, id_, sizeof(id)); + ob_ = DEG_get_original_object(ob); + hash_value_ = BLI_ghashutil_ptrhash(ob_); + + if (DupliObject *dupli = DRW_object_get_dupli(ob)) { + parent_ = DRW_object_get_dupli_parent(ob); + hash_value_ = BLI_ghashutil_combine_hash(hash_value_, BLI_ghashutil_ptrhash(parent_)); + memcpy(id_, dupli->persistent_id, sizeof(id_)); + for (int id : id_) { + if (id == INT_MAX) { + break; + } + hash_value_ = BLI_ghashutil_combine_hash(hash_value_, BLI_ghashutil_inthash(id)); + } } else { - memset(id, 0, sizeof(id)); - } - /* Compute hash on creation so we avoid the cost of it for every sync. */ - hash_value = BLI_ghashutil_ptrhash(ob); - hash_value = BLI_ghashutil_combine_hash(hash_value, BLI_ghashutil_ptrhash(parent)); - for (int i = 0; i < MAX_DUPLI_RECUR; i++) { - if (id[i] != 0) { - hash_value = BLI_ghashutil_combine_hash(hash_value, BLI_ghashutil_inthash(id[i])); - } - else { - break; - } + parent_ = nullptr; + memset(id_, 0, sizeof(id_)); } + if (sub_key_ != 0) { - hash_value = BLI_ghashutil_combine_hash(hash_value, sub_key_); + hash_value_ = BLI_ghashutil_combine_hash(hash_value_, BLI_ghashutil_inthash(sub_key_)); } -#ifdef DEBUG - STRNCPY(name, ob->id.name); -#endif } - ObjectKey(Object *ob, DupliObject *dupli, Object *parent, int sub_key_ = 0) - : ObjectKey(ob, parent, dupli ? dupli->persistent_id : nullptr, sub_key_){}; - - ObjectKey(Object *ob, int sub_key_ = 0) - : ObjectKey(ob, DRW_object_get_dupli(ob), DRW_object_get_dupli_parent(ob), sub_key_){}; - uint64_t hash() const { - return hash_value; + return hash_value_; } bool operator<(const ObjectKey &k) const { - if (ob != k.ob) { - return (ob < k.ob); - } - if (parent != k.parent) { - return (parent < k.parent); - } - if (sub_key_ != k.sub_key_) { - return (sub_key_ < k.sub_key_); - } - return memcmp(id, k.id, sizeof(id)) < 0; + return memcmp(this, &k, sizeof(this)) < 0; } bool operator==(const ObjectKey &k) const { - if (ob != k.ob) { - return false; - } - if (parent != k.parent) { - return false; - } - if (sub_key_ != k.sub_key_) { - return false; - } - return memcmp(id, k.id, sizeof(id)) == 0; + return memcmp(this, &k, sizeof(this)) == 0; } }; @@ -122,9 +96,9 @@ struct ObjectKey { * * \{ */ -struct ObjectHandle : public DrawData { - ObjectKey object_key; - +struct BaseHandle { + /* Accumulated recalc flags, which corresponds to ID->recalc flags. */ + unsigned int recalc; void reset_recalc_flag() { if (recalc != 0) { @@ -133,6 +107,10 @@ struct ObjectHandle : public DrawData { } }; +struct ObjectHandle : public BaseHandle { + ObjectKey object_key; +}; + struct WorldHandle : public DrawData { void reset_recalc_flag() { @@ -155,6 +133,8 @@ class SyncModule { private: Instance &inst_; + Map ob_handles = {}; + public: SyncModule(Instance &inst) : inst_(inst){}; ~SyncModule(){}; diff --git a/source/blender/draw/engines/eevee_next/eevee_velocity.cc b/source/blender/draw/engines/eevee_next/eevee_velocity.cc index 12dba2e7e85..5d03d5bac5b 100644 --- a/source/blender/draw/engines/eevee_next/eevee_velocity.cc +++ b/source/blender/draw/engines/eevee_next/eevee_velocity.cc @@ -154,7 +154,7 @@ bool VelocityModule::step_object_sync(Object *ob, VelocityObjectData &vel = velocity_map.lookup_or_add_default(object_key); vel.obj.ofs[step_] = object_steps_usage[step_]++; vel.obj.resource_id = resource_handle.resource_index(); - vel.id = object_key.hash_value; + vel.id = object_key.hash(); object_steps[step_]->get_or_resize(vel.obj.ofs[step_]) = float4x4_view(ob->object_to_world); if (step_ == STEP_CURRENT) { /* Replace invalid steps. Can happen if object was hidden in one of those steps. */