| … | … | @@ -0,0 +1,43 @@ |
| 1 | ## Import a Blender-bridged graph and try to evaluate it. | |
| 2 | extends SceneTree | |
| 3 | func _init() -> void: | |
| 4 | var a := OS.get_cmdline_user_args() | |
| 5 | var js := FileAccess.get_file_as_string(a[0]) | |
| 6 | var g: ProcNodeGraph = GraphImporter.import_from_json(js) | |
| 7 | if g == null: | |
| 8 | push_error("import returned null"); quit(1); return | |
| 9 | print("imported: %d nodes, %d connections" % [g.get_node_count(), g.get_connection_count()]) | |
| 10 | var missing := 0 | |
| 11 | for i in range(g.get_node_count()): | |
| 12 | var n: ProcNode = g.get_node(i) | |
| 13 | if n == null: | |
| 14 | missing += 1 | |
| 15 | else: | |
| 16 | print(" %2d %s" % [i, n.get_node_type()]) | |
| 17 | print("null nodes: %d" % missing) | |
| 18 | var host := ProcGeometryNode.new() | |
| 19 | host.use_gpu = true | |
| 20 | # THE CAGE. A Blender geometry tree acts on the object's own mesh, which its | |
| 21 | # Group Input carries; proc-nodes now takes the same thing as input_mesh. | |
| 22 | # A box, subdivided, matching the cage the Blender side displaces. | |
| 23 | if a.size() > 1: | |
| 24 | var bm := BoxMesh.new() | |
| 25 | bm.size = Vector3(40.0, 4.0, 40.0) | |
| 26 | bm.subdivide_width = int(a[1]) | |
| 27 | bm.subdivide_depth = int(a[1]) | |
| 28 | bm.subdivide_height = 2 | |
| 29 | host.set_input_mesh(bm) | |
| 30 | print("input mesh: BoxMesh %d subdivisions" % int(a[1])) | |
| 31 | host.set_graph(g) | |
| 32 | get_root().add_child(host) | |
| 33 | var m: ArrayMesh = host.bake_mesh() | |
| 34 | if m == null or m.get_surface_count() == 0: | |
| 35 | print("BAKE: no mesh") | |
| 36 | else: | |
| 37 | var v: PackedVector3Array = m.surface_get_arrays(0)[Mesh.ARRAY_VERTEX] | |
| 38 | var lo := INF | |
| 39 | var hi := -INF | |
| 40 | for p in v: | |
| 41 | lo = minf(lo, p.y); hi = maxf(hi, p.y) | |
| 42 | print("BAKE: %d verts, y %.2f .. %.2f" % [v.size(), lo, hi]) | |
| 43 | quit() |
| … | … | @@ -142,6 +142,22 @@ String GlslEmitContext::in(int p_node_idx, int p_socket) const { |
| 142 | 142 | if (src_node < 0) { |
| 143 | 143 | return literal(p_node_idx, p_socket); |
| 144 | 144 | } |
| 145 | // ⛔ A LOCAL ONLY EXISTS IF ITS PRODUCER IS IN THIS SHADER. | |
| 146 | // | |
| 147 | // param() learned this; in() did not, and nodes that read their inputs | |
| 148 | // directly -- Combine XYZ among them -- go straight through here. The batch | |
| 149 | // for the bridged mountain held nodes 31 and 32 only, and Combine XYZ still | |
| 150 | // emitted `vec3 n31_s0 = vec3(0.0, 0.0, n30_s0);` for a producer that was | |
| 151 | // never written: | |
| 152 | // | |
| 153 | // ERROR: 0:46: 'n30_s0' : undeclared identifier | |
| 154 | // | |
| 155 | // Scoped to the BATCH path by push_constants. compile_to_function emits the | |
| 156 | // whole graph and sets no emitted_nodes at all, so checking there would | |
| 157 | // reduce every input to its default and silently gut the density shader. | |
| 158 | if (push_constants && !is_emitted(src_node)) { | |
| 159 | return literal(p_node_idx, p_socket); | |
| 160 | } | |
| 145 | 161 | const int src_socket = graph->get_input_source_socket(p_node_idx, p_socket); |
| 146 | 162 | const String expr = out(src_node, src_socket); |
| 147 | 163 |
| … | … | @@ -455,6 +455,16 @@ bool GpuCompiler::create_pipeline( |
| 455 | 455 | String err = spirv->get_stage_compile_error(RenderingDevice::SHADER_STAGE_COMPUTE); |
| 456 | 456 | if (!err.is_empty()) { |
| 457 | 457 | UtilityFunctions::push_error("GpuCompiler: Shader compile error: ", err); |
| 458 | // ⛔ PRINT THE TEXT THAT FAILED. A compile error names a line in a | |
| 459 | // shader nobody can see, and "'n30_s0' : undeclared identifier" is | |
| 460 | // unanswerable without the body -- which node emitted, which did not, | |
| 461 | // and what it named. The emitter is the only thing that knows. | |
| 462 | const PackedStringArray lines = p_glsl_source.split("\n"); | |
| 463 | String dump; | |
| 464 | for (int i = 0; i < lines.size(); i++) { | |
| 465 | dump += String::num_int64(i + 1) + ": " + lines[i] + "\n"; | |
| 466 | } | |
| 467 | UtilityFunctions::push_error("GpuCompiler: the shader that failed:\n", dump); | |
| 458 | 468 | return false; |
| 459 | 469 | } |
| 460 | 470 |