318 std::optional<uint32_t> cluster = std::nullopt);
325 std::optional<uint32_t> cluster = std::nullopt);
332 std::optional<uint32_t> cluster = std::nullopt);
344 std::optional<uint32_t> cluster = std::nullopt);
351 std::optional<uint32_t> cluster = std::nullopt);
358 std::optional<uint32_t> cluster = std::nullopt);
386 [[nodiscard]]
bool needs_cluster_id()
const;
393 void set_vertex_binding(uint32_t binding);
403 void set_workgroup_size(uint32_t x);
412 [[nodiscard]] uint64_t
revision() const noexcept {
return m_revision; }
431 void set_density_saturation_count(
float count);
434 void set_capture_growth(
float growth);
437 void set_swallow_base_size(
float size);
440 void set_swallow_growth_rate(
float rate);
443 void set_swallow_max_size(
float size);
446 void set_swallow_dim_factor(
float factor);
449 void set_cross_cluster(
bool enabled);
452 void set_spawn_density_threshold(
float threshold);
483 [[nodiscard]] std::optional<Portal::Graphics::ShaderSpec> build_spec()
const;
501 void process(
float dt)
override;
511 void set_parameter(std::string_view param,
double value)
override;
513 [[nodiscard]] std::optional<double> query_state(std::string_view query)
const override;
517 return "GpuFieldOperator";
527 return binding_count() > 0;
556 uint32_t m_stride_words {};
557 uint32_t m_vertex_binding {};
558 uint32_t m_workgroup_size { 256 };
560 uint64_t m_revision {};
568 [[nodiscard]] std::optional<std::pair<uint32_t, uint32_t>>
575 uint32_t components);
581 std::optional<uint32_t> cluster);
void bind(FieldTarget target, const Kinesis::DualUVField &field, std::optional< uint32_t > cluster=std::nullopt)
Bind a two-component field.
void bind(FieldTarget target, const Kinesis::TemporalSpatialField &field, std::optional< uint32_t > cluster=std::nullopt)
Bind a scalar field of position and time.
~GpuFieldOperator() override=default
std::optional< Portal::Graphics::ShaderSpec > m_spec_cache
void bind(FieldTarget target, const Kinesis::TemporalUVField &field, std::optional< uint32_t > cluster=std::nullopt)
Bind a two-component field of position and time.
SpatialFieldConfig m_field_config
const SpatialFieldConfig & get_field_config() const
The current SpatialFieldConfig: structural fields (which stages exist) and live-tunable values alike.
void bind(FieldTarget target, const Kinesis::DualSpatialField &field, std::optional< uint32_t > cluster=std::nullopt)
Bind a scalar field.
std::string_view get_type_name() const override
Type name for introspection.
std::vector< Binding > m_bindings
size_t binding_count() const
Number of bound fields.
Kakshya::VertexLayout m_layout
uint64_t revision() const noexcept
Monotonic counter incremented whenever build_spec()'s result changes.
uint32_t get_vertex_binding() const noexcept
Get the descriptor binding index the vertex SSBO occupies.
bool demands_full_vertex_restore() const override
True once at least one field is bound: the VertexFieldProcessor this operator drives writes pos += f ...
const Kakshya::VertexLayout & get_layout() const
Layout the emitted shader addresses.
Chain operator that declares Tendency field deformation as a compute shader rather than evaluating it...
Domain-agnostic interpretive lens for network processing.
FieldTarget
What a Tendency drives when applied to a vertex record.
Kinesis::FieldTarget FieldTarget
std::shared_ptr< T > store(std::shared_ptr< T > obj)
Transfer ownership of an existing object to the persistent store for process lifetime.
Complete description of vertex data layout in a buffer.
One authored expression carried as both a host callable and shader text.
Parsed representation of a stringified field lambda.
An authored expression of position and time, shader-only.
std::optional< uint32_t > cluster
Kinesis::FieldSource source
One target and the field driving it.
std::optional< float > absorb_radius
Enables the deterministic claim/absorption pipeline at this distance.
std::optional< float > cell_size
Spatial hash cell size.
float swallow_max_size
ClaimSwallowProcessor: point-size ceiling regardless of swallow count, so one runaway cluster can't d...
float density_saturation_count
HashDensityColorProcessor: neighbour count at which the density ramp saturates to fully warm.
bool cross_cluster
Whether ClaimProcessor and HashDensityColorProcessor may see across cluster boundaries.
float spawn_density_threshold
PopulationSpawnProcessor: real neighbour count (same 27-cell query HashDensityColorProcessor performs...
bool cosmetic_swallow
Whether ClaimSwallowProcessor's cosmetic pass (position snap onto root, size/colour from this cycle's...
float swallow_growth_rate
ClaimSwallowProcessor: point-size increase per particle a survivor swallowed this cycle.
float reserve_fraction
Fraction of extra reserve capacity the geometry buffer allocates beyond the live point count,...
float swallow_base_size
ClaimSwallowProcessor: a survivor's point size the cycle it has swallowed nothing.
bool density_color
Enables neighbour-density colouring (ember-to-white-hot ramp).
bool transfer_on_claim
Whether a claim that crosses a cluster boundary moves the absorbed vertex into the claimant's cluster...
float capture_growth
Scales a claimant's effective capture radius by the cube root of its own currently accreted mass (mut...
float swallow_dim_factor
ClaimSwallowProcessor: brightness multiplier applied to an absorbed particle's cluster colour (0 invi...
Declarative configuration for the GPU-side spatial-relational work a GpuFieldOperator can drive beyon...