1use crate::capacity::floor;
2use crate::{Soft, SoftCapacity, SoftDemand, SoftFrame, SoftInputs, SoftPasses, SoftStreams};
3use dynamis_abi::COUNTER_SOFT_ACTIVE;
4use dynamis_abi::Counters;
5use dynamis_domain::{Domain, Run, StepFacts};
6use dynamis_gpu::GpuContext;
7use dynamis_gpu::Resources;
8use dynamis_pass::{PassGroup, Pipeline, Schedule};
9use wgpu::CommandEncoder;
10
11pub struct SoftDomain;
12
13#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
14pub struct SoftWork {
15 pub uploads: bool,
16}
17
18impl Domain for SoftDomain {
19 const ID: u32 = 3;
20
21 const SIMULATES: bool = true;
22
23 const PASS_EDGES: dynamis_pass::PassEdges = &[SoftPasses::EDGES];
24
25 type Demand = SoftDemand;
26 type Inputs = SoftInputs;
27 type Work = SoftWork;
28 type Streams = SoftStreams;
29 type Planner = ();
30 type Passes = SoftPasses;
31 type Runtime = Soft;
32 type Frame = SoftFrame;
33 type Capacity = SoftCapacity;
34
35 fn minimum() -> SoftDemand {
36 floor()
37 }
38
39 fn occupied(inputs: &SoftInputs) -> bool {
40 inputs.particles > 0
41 }
42
43 fn pending(work: &SoftWork) -> bool {
44 work.uploads
45 }
46
47 fn active(measured: &Counters) -> bool {
48 measured[COUNTER_SOFT_ACTIVE] != 0
49 }
50
51 fn pass_groups() -> &'static [PassGroup] {
52 &[SoftPasses::GROUP]
53 }
54
55 fn resolve(pipeline: &Pipeline) -> SoftPasses {
56 SoftPasses::resolve(pipeline)
57 }
58
59 fn build(context: &GpuContext, streams: &impl Resources, passes: SoftPasses) -> Soft {
60 Soft::new(context, streams, passes)
61 }
62
63 fn frame(facts: &StepFacts, inputs: &SoftInputs, run: Run) -> SoftFrame {
64 SoftFrame {
65 params: facts.params,
66 simulating: run.awake,
67 material: inputs.material,
68 }
69 }
70
71 fn capacity(streams: &SoftStreams) -> SoftCapacity {
72 crate::capacity(streams)
73 }
74
75 fn record(
76 runtime: &Soft,
77 pass: u32,
78 schedule: &mut Schedule,
79 encoder: &mut CommandEncoder,
80 streams: &impl Resources,
81 frame: &SoftFrame,
82 ) {
83 runtime.record(pass, schedule, encoder, streams, frame);
84 }
85}