Implement refcounting for material caches.

This commit is contained in:
Relintai 2021-08-03 01:08:50 +02:00
parent 8f989f7ae0
commit 94c9fc39ac
7 changed files with 103 additions and 10 deletions

View File

@ -29,6 +29,19 @@ void TerraMaterialCache::set_initialized(const bool value) {
_initialized = value;
}
int TerraMaterialCache::get_ref_count() {
return _ref_count;
}
void TerraMaterialCache::set_ref_count(const int value) {
_ref_count = value;
}
void TerraMaterialCache::inc_ref_count() {
_ref_count += 1;
}
void TerraMaterialCache::dec_ref_count() {
_ref_count -= 1;
}
//Materials
Ref<Material> TerraMaterialCache::material_get(const int index) {
ERR_FAIL_INDEX_V(index, _materials.size(), Ref<Material>(NULL));
@ -143,7 +156,7 @@ void TerraMaterialCache::setup_material_albedo(Ref<Texture> texture) {
}
TerraMaterialCache::TerraMaterialCache() {
material_users = 0;
_ref_count = 0;
_initialized = false;
}
@ -157,6 +170,12 @@ void TerraMaterialCache::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_initialized", "value"), &TerraMaterialCache::set_initialized);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "initialized"), "set_initialized", "get_initialized");
ClassDB::bind_method(D_METHOD("get_ref_count"), &TerraMaterialCache::get_ref_count);
ClassDB::bind_method(D_METHOD("set_ref_count", "value"), &TerraMaterialCache::set_ref_count);
ADD_PROPERTY(PropertyInfo(Variant::INT, "mat_ref_count"), "set_ref_count", "get_ref_count");
ClassDB::bind_method(D_METHOD("inc_ref_count"), &TerraMaterialCache::inc_ref_count);
ClassDB::bind_method(D_METHOD("dec_ref_count"), &TerraMaterialCache::dec_ref_count);
BIND_VMETHOD(MethodInfo("_setup_material_albedo", PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")));
ClassDB::bind_method(D_METHOD("material_get", "index"), &TerraMaterialCache::material_get);

View File

@ -51,6 +51,11 @@ public:
bool get_initialized();
void set_initialized(const bool value);
int get_ref_count();
void set_ref_count(const int value);
void inc_ref_count();
void dec_ref_count();
Ref<Material> material_get(const int index);
Ref<Material> material_lod_get(const int index);
void material_add(const Ref<Material> &value);
@ -84,8 +89,8 @@ protected:
Vector<Ref<TerraSurface>> _surfaces;
Vector<Ref<Material>> _materials;
int material_users;
int _ref_count;
};
#endif

View File

@ -84,6 +84,12 @@ Ref<TerraMaterialCache> TerramanLibrary::_material_cache_get(const int key) {
ERR_FAIL_V_MSG(Ref<TerraMaterialCache>(), "This TerramanLibrary doesn't support cached materials!");
}
void TerramanLibrary::material_cache_unref(const int key) {
call("_material_cache_unref", key);
}
void TerramanLibrary::_material_cache_unref(const int key) {
}
void TerramanLibrary::material_add(const Ref<Material> &value) {
ERR_FAIL_COND(!value.is_valid());
@ -158,6 +164,12 @@ Ref<TerraMaterialCache> TerramanLibrary::_liquid_material_cache_get(const int ke
ERR_FAIL_V_MSG(Ref<TerraMaterialCache>(), "This TerramanLibrary doesn't support cached liquid materials!");
}
void TerramanLibrary::liquid_material_cache_unref(const int key) {
call("_liquid_material_cache_unref", key);
}
void TerramanLibrary::_liquid_material_cache_unref(const int key) {
}
void TerramanLibrary::liquid_material_add(const Ref<Material> &value) {
ERR_FAIL_COND(!value.is_valid());
@ -232,6 +244,12 @@ Ref<TerraMaterialCache> TerramanLibrary::_prop_material_cache_get(const int key)
ERR_FAIL_V_MSG(Ref<TerraMaterialCache>(), "This TerramanLibrary doesn't support cached prop materials!");
}
void TerramanLibrary::prop_material_cache_unref(const int key) {
call("_prop_material_cache_unref", key);
}
void TerramanLibrary::_prop_material_cache_unref(const int key) {
}
void TerramanLibrary::prop_material_add(const Ref<Material> &value) {
ERR_FAIL_COND(!value.is_valid());
@ -351,7 +369,8 @@ void TerramanLibrary::_bind_methods() {
BIND_VMETHOD(MethodInfo("_setup_material_albedo", PropertyInfo(Variant::INT, "material_index"), PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")));
BIND_VMETHOD(MethodInfo("_material_cache_get_key", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "TerraChunk")));
BIND_VMETHOD(MethodInfo("_material_cache_get", PropertyInfo(Variant::OBJECT, "key", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache")));
BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "ret", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"), "_material_cache_get", PropertyInfo(Variant::INT, "key")));
BIND_VMETHOD(MethodInfo("_material_cache_unref", PropertyInfo(Variant::INT, "key")));
ClassDB::bind_method(D_METHOD("material_get", "index"), &TerramanLibrary::material_get);
ClassDB::bind_method(D_METHOD("material_lod_get", "index"), &TerramanLibrary::material_lod_get);
@ -360,6 +379,8 @@ void TerramanLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("_material_cache_get_key", "chunk"), &TerramanLibrary::_material_cache_get_key);
ClassDB::bind_method(D_METHOD("material_cache_get", "key"), &TerramanLibrary::material_cache_get);
ClassDB::bind_method(D_METHOD("_material_cache_get", "key"), &TerramanLibrary::_material_cache_get);
ClassDB::bind_method(D_METHOD("material_cache_unref", "key"), &TerramanLibrary::material_cache_unref);
ClassDB::bind_method(D_METHOD("_material_cache_unref", "key"), &TerramanLibrary::_material_cache_unref);
ClassDB::bind_method(D_METHOD("material_add", "value"), &TerramanLibrary::material_add);
ClassDB::bind_method(D_METHOD("material_set", "index", "value"), &TerramanLibrary::material_set);
@ -372,7 +393,8 @@ void TerramanLibrary::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "materials", PROPERTY_HINT_NONE, "17/17:Material", PROPERTY_USAGE_DEFAULT, "Material"), "materials_set", "materials_get");
BIND_VMETHOD(MethodInfo("_liquid_material_cache_get_key", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "TerraChunk")));
BIND_VMETHOD(MethodInfo("_liquid_material_cache_get", PropertyInfo(Variant::OBJECT, "key", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache")));
BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "ret", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"), "_liquid_material_cache_get", PropertyInfo(Variant::INT, "key")));
BIND_VMETHOD(MethodInfo("_liquid_material_cache_unref", PropertyInfo(Variant::INT, "key")));
ClassDB::bind_method(D_METHOD("liquid_material_get", "index"), &TerramanLibrary::liquid_material_get);
ClassDB::bind_method(D_METHOD("liquid_material_lod_get", "index"), &TerramanLibrary::liquid_material_lod_get);
@ -381,6 +403,8 @@ void TerramanLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("_liquid_material_cache_get_key", "chunk"), &TerramanLibrary::_liquid_material_cache_get_key);
ClassDB::bind_method(D_METHOD("liquid_material_cache_get", "key"), &TerramanLibrary::liquid_material_cache_get);
ClassDB::bind_method(D_METHOD("_liquid_material_cache_get", "key"), &TerramanLibrary::_liquid_material_cache_get);
ClassDB::bind_method(D_METHOD("liquid_material_cache_unref", "key"), &TerramanLibrary::liquid_material_cache_unref);
ClassDB::bind_method(D_METHOD("_liquid_material_cache_unref", "key"), &TerramanLibrary::_liquid_material_cache_unref);
ClassDB::bind_method(D_METHOD("liquid_material_add", "value"), &TerramanLibrary::liquid_material_add);
ClassDB::bind_method(D_METHOD("liquid_material_set", "index", "value"), &TerramanLibrary::liquid_material_set);
@ -393,7 +417,8 @@ void TerramanLibrary::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "liquid_materials", PROPERTY_HINT_NONE, "17/17:Material", PROPERTY_USAGE_DEFAULT, "Material"), "liquid_materials_set", "liquid_materials_get");
BIND_VMETHOD(MethodInfo("_prop_material_cache_get_key", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "TerraChunk")));
BIND_VMETHOD(MethodInfo("_prop_material_cache_get", PropertyInfo(Variant::OBJECT, "key", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache")));
BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "ret", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"), "_prop_material_cache_get", PropertyInfo(Variant::INT, "key")));
BIND_VMETHOD(MethodInfo("_prop_material_cache_unref", PropertyInfo(Variant::INT, "key")));
ClassDB::bind_method(D_METHOD("prop_material_get", "index"), &TerramanLibrary::prop_material_get);
ClassDB::bind_method(D_METHOD("prop_material_lod_get", "index"), &TerramanLibrary::prop_material_lod_get);
@ -402,6 +427,8 @@ void TerramanLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("_prop_material_cache_get_key", "chunk"), &TerramanLibrary::_prop_material_cache_get_key);
ClassDB::bind_method(D_METHOD("prop_material_cache_get", "key"), &TerramanLibrary::prop_material_cache_get);
ClassDB::bind_method(D_METHOD("_prop_material_cache_get", "key"), &TerramanLibrary::_prop_material_cache_get);
ClassDB::bind_method(D_METHOD("prop_material_cache_unref", "key"), &TerramanLibrary::prop_material_cache_unref);
ClassDB::bind_method(D_METHOD("_prop_material_cache_unref", "key"), &TerramanLibrary::_prop_material_cache_unref);
ClassDB::bind_method(D_METHOD("prop_material_add", "value"), &TerramanLibrary::prop_material_add);
ClassDB::bind_method(D_METHOD("prop_material_set", "index", "value"), &TerramanLibrary::prop_material_set);

View File

@ -76,6 +76,8 @@ public:
virtual void _material_cache_get_key(Ref<TerraChunk> chunk);
Ref<TerraMaterialCache> material_cache_get(const int key);
virtual Ref<TerraMaterialCache> _material_cache_get(const int key);
void material_cache_unref(const int key);
virtual void _material_cache_unref(const int key);
void material_add(const Ref<Material> &value);
void material_set(const int index, const Ref<Material> &value);
@ -93,6 +95,8 @@ public:
virtual void _liquid_material_cache_get_key(Ref<TerraChunk> chunk);
Ref<TerraMaterialCache> liquid_material_cache_get(const int key);
virtual Ref<TerraMaterialCache> _liquid_material_cache_get(const int key);
void liquid_material_cache_unref(const int key);
virtual void _liquid_material_cache_unref(const int key);
void liquid_material_add(const Ref<Material> &value);
void liquid_material_set(const int index, const Ref<Material> &value);
@ -110,6 +114,8 @@ public:
virtual void _prop_material_cache_get_key(Ref<TerraChunk> chunk);
Ref<TerraMaterialCache> prop_material_cache_get(const int key);
virtual Ref<TerraMaterialCache> _prop_material_cache_get(const int key);
void prop_material_cache_unref(const int key);
virtual void _prop_material_cache_unref(const int key);
void prop_material_add(const Ref<Material> &value);
void prop_material_set(const int index, const Ref<Material> &value);
@ -157,9 +163,9 @@ protected:
static void _bind_methods();
bool _initialized;
Vector<Ref<Material> > _materials;
Vector<Ref<Material> > _liquid_materials;
Vector<Ref<Material> > _prop_materials;
Vector<Ref<Material>> _materials;
Vector<Ref<Material>> _liquid_materials;
Vector<Ref<Material>> _prop_materials;
};
#endif // TERRA_LIBRARY_H

View File

@ -104,8 +104,14 @@ void TerramanLibraryMergerPCM::_material_cache_get_key(Ref<TerraChunk> chunk) {
_cache_mutex.lock();
if (_material_cache.has(hash)) {
Ref<TerraMaterialCachePCM> cc = _material_cache[hash];
if (cc.is_valid()) {
cc->inc_ref_count();
}
_cache_mutex.unlock();
return;
}
@ -113,6 +119,7 @@ void TerramanLibraryMergerPCM::_material_cache_get_key(Ref<TerraChunk> chunk) {
Ref<TerraMaterialCachePCM> cache;
cache.instance();
cache->inc_ref_count();
cache->set_texture_flags(get_texture_flags());
cache->set_max_atlas_size(get_max_atlas_size());
@ -171,6 +178,28 @@ Ref<TerraMaterialCache> TerramanLibraryMergerPCM::_material_cache_get(const int
return _material_cache[key];
}
void TerramanLibraryMergerPCM::_material_cache_unref(const int key) {
_cache_mutex.lock();
if (!_material_cache.has(key)) {
return;
}
Ref<TerraMaterialCachePCM> cc = _material_cache[key];
if (!cc.is_valid()) {
return;
}
cc->dec_ref_count();
if (cc->get_ref_count() <= 0) {
_material_cache.erase(key);
}
_cache_mutex.unlock();
}
int TerramanLibraryMergerPCM::get_texture_flags() const {
return _packer->get_texture_flags();
}

View File

@ -56,6 +56,7 @@ public:
bool _supports_caching();
void _material_cache_get_key(Ref<TerraChunk> chunk);
Ref<TerraMaterialCache> _material_cache_get(const int key);
void _material_cache_unref(const int key);
int get_texture_flags() const;
void set_texture_flags(const int flags);

View File

@ -938,6 +938,12 @@ void TerraChunk::enter_tree() {
void TerraChunk::exit_tree() {
_is_in_tree = false;
if (_library.is_valid() && _library->supports_caching()) {
if (material_cache_key_has()) {
_library->material_cache_unref(material_cache_key_get());
}
}
if (has_method("_exit_tree"))
call("_exit_tree");
}