| … | … | @@ -983,12 +983,61 @@ static bool _batch_contains(const GpuBatch &p_batch, int p_node_idx) { |
| 983 | 983 | return false; |
| 984 | 984 | } |
| 985 | 985 | |
| 986 | // ⛔ A CONNECTED INPUT WHOSE PRODUCER IS NOT IN THE SHADER IS A REFUSAL. |
| 987 | // |
| 988 | // GlslEmitContext::in() falls back to the socket's LITERAL when the producer is |
| 989 | // not emitted here. That keeps the shader COMPILING -- and makes it compute |
| 990 | // something else. The bridged mountain's batch was [CombineXYZ, SetPosition] |
| 991 | // with the Switch that carries the height OUTSIDE it, so Combine XYZ's Z read |
| 992 | // its default 0.0 and the displacement vanished: y -2..28.85 on the CPU against |
| 993 | // y -2..2 on the GPU, with no error anywhere. I turned a loud compile failure |
| 994 | // into a quiet wrong answer when I added that fallback. |
| 995 | // |
| 996 | // Fused VALUE nodes were never checked at all -- the dispatch loop `continue`s |
| 997 | // past them before the representability test. This checks every node in the |
| 998 | // batch, and one failure sends the WHOLE batch to the CPU: a partial batch is |
| 999 | // how two halves of a graph end up computing different functions. |
| 1000 | static bool _batch_is_representable(ProcEvalContext &p_ctx, const GpuBatch &p_batch) { |
| 1001 | for (int f = 0; f < p_batch.fused_nodes.size(); f++) { |
| 1002 | const int node_idx = p_batch.fused_nodes[f]; |
| 1003 | Ref<ProcNode> node = p_ctx.graph->get_node(node_idx); |
| 1004 | if (node.is_null()) { |
| 1005 | continue; |
| 1006 | } |
| 1007 | const PackedInt32Array pc_map = node->get_push_constant_sockets(); |
| 1008 | for (int si = 0; si < node->get_input_count(); si++) { |
| 1009 | if (node->get_input_type(si) == (int)SocketType::Geometry) { |
| 1010 | continue; |
| 1011 | } |
| 1012 | if (!p_ctx.is_input_connected(node_idx, si)) { |
| 1013 | continue; |
| 1014 | } |
| 1015 | // Produced inside this shader: it is a local, and correct. |
| 1016 | if (_batch_contains(p_batch, p_ctx.graph->get_input_source_node(node_idx, si))) { |
| 1017 | continue; |
| 1018 | } |
| 1019 | // Otherwise the only channel is a push constant, and only for a |
| 1020 | // value that is ONE value -- never a field. |
| 1021 | if (!pc_map.has(si)) { |
| 1022 | return false; |
| 1023 | } |
| 1024 | const SocketValue raw = p_ctx._read_input_raw(node_idx, si); |
| 1025 | if (raw.is_field || raw.is_lazy) { |
| 1026 | return false; |
| 1027 | } |
| 1028 | } |
| 1029 | } |
| 1030 | return true; |
| 1031 | } |
| 1032 | |
| 986 | 1033 | void GraphExecutor::_execute_gpu_batch(ProcEvalContext &p_ctx, const GpuBatch &p_batch, const ExecutionPlan &p_plan) { |
| 987 | 1034 | RenderingDevice *rd = p_ctx.gpu_buffers.get_rd(); |
| 988 | 1035 | if (!rd) { |
| 989 | 1036 | return; |
| 990 | 1037 | } |
| 991 | 1038 | |
| 1039 | |
| 1040 | |
| 992 | 1041 | // For Phase 4, process each node in the batch individually. |
| 993 | 1042 | // Future phases will fuse multiple nodes into a single shader dispatch. |
| 994 | 1043 | for (int b = 0; b < p_batch.node_count; b++) { |
| … | … | @@ -1447,6 +1496,18 @@ Ref<ProcGeometry> GraphExecutor::execute( |
| 1447 | 1496 | // Check for GPU batch at this position |
| 1448 | 1497 | if (gpu_available) { |
| 1449 | 1498 | int batch_idx = p_plan.find_gpu_batch(i); |
| 1499 | // ⛔ REFUSE HERE, NOT INSIDE THE BATCH. An unrepresentable batch has |
| 1500 | // to fall through to the ORDINARY per-node path, because that path |
| 1501 | // is where _bind_context_or_defer lives -- the lazy-field binding a |
| 1502 | // bare node->execute() knows nothing about. Running the nodes by |
| 1503 | // hand inside _execute_gpu_batch reported them as CPU and still got |
| 1504 | // the wrong answer: the mountain stayed flat, y -2..2 against the |
| 1505 | // CPU path's y -2..28.85, because the deferred field was never |
| 1506 | // materialised. |
| 1507 | if (batch_idx >= 0 && |
| 1508 | !_batch_is_representable(ctx, p_plan.gpu_batches[batch_idx])) { |
| 1509 | batch_idx = -1; |
| 1510 | } |
| 1450 | 1511 | if (batch_idx >= 0) { |
| 1451 | 1512 | _execute_gpu_batch(ctx, p_plan.gpu_batches[batch_idx], p_plan); |
| 1452 | 1513 | i += p_plan.gpu_batches[batch_idx].node_count - 1; |