Fix graph not recompiling after changing a subresource

This commit is contained in:
Marc Gilleron 2021-09-22 20:28:17 +01:00
parent ba8d9aad52
commit 62c807fa71
4 changed files with 71 additions and 10 deletions

View File

@ -68,7 +68,7 @@ public:
void find_terminal_nodes(std::vector<uint32_t> &node_ids) const;
template <typename F>
inline void for_each_node(F f) const {
inline void for_each_node_const(F f) const {
for (auto it = _nodes.begin(); it != _nodes.end(); ++it) {
const Node *node = it->second;
ERR_CONTINUE(node == nullptr);
@ -76,6 +76,15 @@ public:
}
}
template <typename F>
inline void for_each_node(F f) {
for (auto it = _nodes.begin(); it != _nodes.end(); ++it) {
Node *node = it->second;
ERR_CONTINUE(node == nullptr);
f(*node);
}
}
void copy_from(const ProgramGraph &other, bool copy_subresources);
void get_connections(std::vector<ProgramGraph::Connection> &connections) const;
//void get_connections_from_and_to(std::vector<ProgramGraph::Connection> &connections, uint32_t node_id) const;

View File

@ -1,4 +1,5 @@
#include "voxel_generator_graph.h"
#include "../../util/macros.h"
#include "../../util/profiling.h"
#include "../../util/profiling_clock.h"
#include "voxel_graph_node_db.h"
@ -17,6 +18,14 @@ VoxelGeneratorGraph::~VoxelGeneratorGraph() {
}
void VoxelGeneratorGraph::clear() {
_graph.for_each_node([this](ProgramGraph::Node &node) {
for (size_t i = 0; i < node.params.size(); ++i) {
Ref<Resource> resource = node.params[i];
if (resource.is_valid()) {
unregister_subresource(**resource);
}
}
});
_graph.clear();
{
RWLockWrite wlock(_runtime_lock);
@ -54,7 +63,14 @@ uint32_t VoxelGeneratorGraph::create_node(NodeTypeID type_id, Vector2 position,
}
void VoxelGeneratorGraph::remove_node(uint32_t node_id) {
ERR_FAIL_COND(_graph.try_get_node(node_id) == nullptr);
ProgramGraph::Node *node = _graph.try_get_node(node_id);
ERR_FAIL_COND(node == nullptr);
for (size_t i = 0; i < node->params.size(); ++i) {
Ref<Resource> resource = node->params[i];
if (resource.is_valid()) {
unregister_subresource(**resource);
}
}
_graph.remove_node(node_id);
emit_changed();
}
@ -141,7 +157,18 @@ void VoxelGeneratorGraph::set_node_param(uint32_t node_id, uint32_t param_index,
ERR_FAIL_INDEX(param_index, node->params.size());
if (node->params[param_index] != value) {
Ref<Resource> prev_resource = node->params[param_index];
if (prev_resource.is_valid()) {
unregister_subresource(**prev_resource);
}
node->params[param_index] = value;
Ref<Resource> resource = value;
if (resource.is_valid()) {
register_subresource(**resource);
}
emit_changed();
}
}
@ -569,6 +596,8 @@ VoxelGenerator::Result VoxelGeneratorGraph::generate_block(VoxelBlockRequest &in
}
VoxelGraphRuntime::CompilationResult VoxelGeneratorGraph::compile() {
const int64_t time_before = OS::get_singleton()->get_ticks_usec();
std::shared_ptr<Runtime> r = std::make_shared<Runtime>();
VoxelGraphRuntime &runtime = r->runtime;
@ -694,6 +723,9 @@ VoxelGraphRuntime::CompilationResult VoxelGeneratorGraph::compile() {
RWLockWrite wlock(_runtime_lock);
_runtime = r;
const int64_t time_spent = OS::get_singleton()->get_ticks_usec() - time_before;
PRINT_VERBOSE(String("Voxel graph compiled in {0} us").format(varray(time_spent)));
return result;
}
@ -1199,15 +1231,35 @@ static bool load_graph_from_variant_data(ProgramGraph &graph, Dictionary data) {
}
void VoxelGeneratorGraph::load_graph_from_variant_data(Dictionary data) {
clear();
if (::load_graph_from_variant_data(_graph, data)) {
_graph.for_each_node([this](ProgramGraph::Node &node) {
for (size_t i = 0; i < node.params.size(); ++i) {
Ref<Resource> resource = node.params[i];
if (resource.is_valid()) {
register_subresource(**resource);
}
}
});
// It's possible to auto-compile on load because `graph_data` is the only property set by the loader,
// which is enough to have all information we need
compile();
} else {
_graph.clear();
}
}
void VoxelGeneratorGraph::register_subresource(Resource &resource) {
resource.connect(CoreStringNames::get_singleton()->changed, this, "_on_subresource_changed");
}
void VoxelGeneratorGraph::unregister_subresource(Resource &resource) {
resource.disconnect(CoreStringNames::get_singleton()->changed, this, "_on_subresource_changed");
}
// Debug land
float VoxelGeneratorGraph::debug_measure_microseconds_per_voxel(bool singular) {
@ -1400,9 +1452,9 @@ Dictionary VoxelGeneratorGraph::_b_compile() {
return d;
}
// void VoxelGeneratorGraph::_on_subresource_changed() {
// emit_changed();
// }
void VoxelGeneratorGraph::_on_subresource_changed() {
emit_changed();
}
void VoxelGeneratorGraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &VoxelGeneratorGraph::clear);
@ -1476,7 +1528,7 @@ void VoxelGeneratorGraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_graph_data", "data"), &VoxelGeneratorGraph::load_graph_from_variant_data);
ClassDB::bind_method(D_METHOD("_get_graph_data"), &VoxelGeneratorGraph::get_graph_as_variant_data);
// ClassDB::bind_method(D_METHOD("_on_subresource_changed"), &VoxelGeneratorGraph::_on_subresource_changed);
ClassDB::bind_method(D_METHOD("_on_subresource_changed"), &VoxelGeneratorGraph::_on_subresource_changed);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "graph_data", PROPERTY_HINT_NONE, "",
PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL),

View File

@ -159,6 +159,9 @@ public:
private:
Dictionary get_graph_as_variant_data() const;
void load_graph_from_variant_data(Dictionary data);
void register_subresource(Resource &resource);
void unregister_subresource(Resource &resource);
void _on_subresource_changed();
int _b_get_node_type_count() const;
Dictionary _b_get_node_type_info(int type_id) const;
@ -171,9 +174,6 @@ private:
Vector2 _b_debug_analyze_range(Vector3 min_pos, Vector3 max_pos) const;
Dictionary _b_compile();
void _on_subresource_changed();
void connect_to_subresource_changes();
struct WeightOutput {
unsigned int layer_index;
unsigned int output_buffer_index;

View File

@ -83,7 +83,7 @@ VoxelGraphRuntime::CompilationResult VoxelGraphRuntime::_compile(const ProgramGr
std::unordered_map<uint32_t, uint32_t> node_id_to_dependency_graph;
// Not using the generic `get_terminal_nodes` function because our terminal nodes do have outputs
graph.for_each_node([&terminal_nodes](const ProgramGraph::Node &node) {
graph.for_each_node_const([&terminal_nodes](const ProgramGraph::Node &node) {
const VoxelGraphNodeDB::NodeType &type = VoxelGraphNodeDB::get_singleton()->get_type(node.type_id);
if (type.category == VoxelGraphNodeDB::CATEGORY_OUTPUT) {
terminal_nodes.push_back(node.id);