Fix #146345: assert when tracing closure value through nested zones
There were two issues: * Missing null checks when the compute context of a socket can't be detected statically. * Incorrect parent compute context detection for closures. The tricky aspect is that closures can be evaluated in a different compute context from where they are created. Pull Request: https://projects.blender.org/blender/blender/pulls/146922
This commit is contained in:
@@ -413,6 +413,7 @@ const ComputeContext *compute_context_for_zone(const bke::bNodeTreeZone &zone,
|
||||
source_location.compute_context_hash = parent_compute_context ?
|
||||
parent_compute_context->hash() :
|
||||
ComputeContextHash{};
|
||||
source_location.compute_context = parent_compute_context;
|
||||
return compute_context_for_closure_evaluation(parent_compute_context,
|
||||
output_node.output_socket(0),
|
||||
compute_context_cache,
|
||||
|
||||
@@ -29,6 +29,8 @@ struct ClosureSourceLocation {
|
||||
const bNodeTree *tree;
|
||||
int closure_output_node_id;
|
||||
ComputeContextHash compute_context_hash;
|
||||
/** Optional actual compute context. If it is set, its hash should be the same as above. */
|
||||
const ComputeContext *compute_context = nullptr;
|
||||
};
|
||||
|
||||
struct ClosureEvalLog {
|
||||
|
||||
@@ -723,7 +723,8 @@ class ShaderNodesInliner {
|
||||
closure_output_node.identifier,
|
||||
closure_zone_value->closure_creation_context ?
|
||||
closure_zone_value->closure_creation_context->hash() :
|
||||
ComputeContextHash{}};
|
||||
ComputeContextHash{},
|
||||
closure_zone_value->closure_creation_context};
|
||||
const bke::EvaluateClosureComputeContext &closure_eval_context =
|
||||
compute_context_cache_.for_evaluate_closure(socket.context,
|
||||
evaluate_closure_node->identifier,
|
||||
|
||||
@@ -68,6 +68,9 @@ static BundleSyncState get_sync_state_separate_bundle(
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, *src_bundle_socket);
|
||||
if (!current_context) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
const LinkedBundleSignatures linked_signatures = gather_linked_origin_bundle_signatures(
|
||||
current_context, *src_bundle_socket, compute_context_cache);
|
||||
if (linked_signatures.items.is_empty()) {
|
||||
@@ -103,6 +106,9 @@ static BundleSyncState get_sync_state_combine_bundle(
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, *src_bundle_socket);
|
||||
if (!current_context) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
const LinkedBundleSignatures linked_signatures = gather_linked_target_bundle_signatures(
|
||||
current_context, *src_bundle_socket, compute_context_cache);
|
||||
if (linked_signatures.items.is_empty()) {
|
||||
@@ -137,6 +143,9 @@ static ClosureSyncState get_sync_state_closure_output(
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, *src_closure_socket);
|
||||
if (!current_context) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
const LinkedClosureSignatures linked_signatures = gather_linked_target_closure_signatures(
|
||||
current_context, *src_closure_socket, compute_context_cache);
|
||||
if (linked_signatures.items.is_empty()) {
|
||||
@@ -171,6 +180,9 @@ static ClosureSyncState get_sync_state_evaluate_closure(
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, *src_closure_socket);
|
||||
if (!current_context) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
const LinkedClosureSignatures linked_signatures = gather_linked_origin_closure_signatures(
|
||||
current_context, *src_closure_socket, compute_context_cache);
|
||||
if (linked_signatures.items.is_empty()) {
|
||||
|
||||
@@ -204,7 +204,8 @@ static Vector<SocketInContext> find_target_sockets_through_contexts(
|
||||
&node->owner_tree(),
|
||||
ClosureSourceLocation{&closure_tree,
|
||||
closure_output_node->identifier,
|
||||
origin_socket.context_hash()});
|
||||
origin_socket.context_hash(),
|
||||
origin_socket.context});
|
||||
if (closure_context.is_recursive()) {
|
||||
continue;
|
||||
}
|
||||
@@ -373,17 +374,22 @@ static Vector<SocketInContext> find_origin_sockets_through_contexts(
|
||||
if (!zones->link_between_zones_is_allowed(from_zone, to_zone)) {
|
||||
continue;
|
||||
}
|
||||
const Vector<const bke::bNodeTreeZone *> zones_to_enter = zones->get_zones_to_enter(
|
||||
from_zone, to_zone);
|
||||
const ComputeContext *compute_context = socket.context;
|
||||
for (int i = zones_to_enter.size() - 1; i >= 0; i--) {
|
||||
if (!compute_context) {
|
||||
/* There must be a compute context when we are in a zone. */
|
||||
BLI_assert_unreachable();
|
||||
return found_origins.extract_vector();
|
||||
for (const bke::bNodeTreeZone *zone = to_zone; zone != from_zone; zone = zone->parent_zone)
|
||||
{
|
||||
if (const auto *evaluate_closure_context =
|
||||
dynamic_cast<const bke::EvaluateClosureComputeContext *>(compute_context))
|
||||
{
|
||||
const std::optional<nodes::ClosureSourceLocation> &source_location =
|
||||
evaluate_closure_context->closure_source_location();
|
||||
/* This is expected to be available during value tracing. */
|
||||
BLI_assert(source_location);
|
||||
BLI_assert(source_location->compute_context);
|
||||
compute_context = source_location->compute_context;
|
||||
}
|
||||
else {
|
||||
compute_context = compute_context->parent();
|
||||
}
|
||||
/* Each zone corresponds to one compute context level. */
|
||||
compute_context = compute_context->parent();
|
||||
}
|
||||
add_if_new({compute_context, from_socket}, bundle_path);
|
||||
}
|
||||
@@ -457,7 +463,8 @@ static Vector<SocketInContext> find_origin_sockets_through_contexts(
|
||||
&node->owner_tree(),
|
||||
ClosureSourceLocation{&closure_tree,
|
||||
closure_output_node->identifier,
|
||||
origin_socket.context_hash()});
|
||||
origin_socket.context_hash(),
|
||||
origin_socket.context});
|
||||
if (closure_context.is_recursive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user