#ifndef PROC_NODES_GPU_COMPILER_H
#define PROC_NODES_GPU_COMPILER_H
#include "../graph/proc_node.h"
#include <godot_cpp/classes/rendering_device.hpp>
#include <godot_cpp/variant/rid.hpp>
namespace godot {
struct GpuBatch {
int first_index = 0; // Index into ExecutionPlan::execution_order
int node_count = 0; // Number of consecutive nodes in this batch
// THE NODES EMITTED INTO THIS SHADER, in topological order, ending with the
// geometry node that writes `pos`. Everything before it is a value/field
// producer whose arithmetic is inlined rather than computed on the CPU and
// squeezed through a push constant.
Vector<int> fused_nodes;
RID shader; // Compiled compute shader
RID pipeline; // Compute pipeline
String compiled_glsl; // For debugging
};
class ProcNodeGraph;
class GpuCompiler {
public:
// Compile batch of nodes into one GLSL compute shader
static String compile_batch(
const Vector<Ref<ProcNode>> &p_nodes,
const Vector<int> &p_node_indices,
const ProcNodeGraph *p_graph = nullptr);
// Create RenderingDevice pipeline from GLSL source
static bool create_pipeline(
RenderingDevice *p_rd,
const String &p_glsl_source,
GpuBatch &r_batch);
// Destroy pipeline + shader
static void destroy_pipeline(RenderingDevice *p_rd, GpuBatch &p_batch);
// Compile graph to a standalone GLSL function for external systems (e.g. dc-terrain)
// Returns: GLSL code with a function `float proc_density(vec3 pos)` that evaluates
// the node graph at a world position. Includes noise library if needed.
// When p_clamp_octaves is true, integer socket defaults (octave counts) are wrapped
// with min(N, pn_max_octaves) so an external caller can enforce Nyquist limits.
// p_graph is what lets a node resolve its INPUTS: without it the emitter can
// only bake each node's own socket defaults, which is why values could not
// travel between nodes at all. See docs/glsl-emitter-design.md.
static String compile_to_function(
const Vector<Ref<ProcNode>> &p_nodes,
const Vector<int> &p_node_indices,
const String &p_function_name = "proc_density",
bool p_clamp_octaves = false,
const ProcNodeGraph *p_graph = nullptr);
// GLSL noise library (simplex 3D + fBM)
static String get_erosion_library_glsl();
// Full shader template with placeholders
static String get_shader_template();
};
} // namespace godot
#endif // PROC_NODES_GPU_COMPILER_H