use super::FrameParams;
use super::dispatch::{
CONTACT_ARCHIVE, FREEZE_CONTACTS, RESTING_GATHER, SORT_RESTING, THAW_CONTACTS,
};
use super::stage::{
CONTACT, CORE, GEOMETRY, IDENTITY, RO, RW, Stage, UNIFORM, shape_resources, whole,
};
use crate::dynamics::buffers::WorldBuffers;
use dynamis_gpu::{ComputeRecorder, GpuContext};
use dynamis_layout::{
COUNTER_ARCHIVED, COUNTER_CONTACTS, COUNTER_ENTRIES, COUNTER_EVENTS, COUNTER_LARGE,
COUNTER_RESTING, COUNTER_RESTING_GATHER, COUNTER_RESTING_INDEX, COUNTER_RESTING_PENDING,
COUNTER_SLEPT, COUNTER_SPILLOVER_EVENTS, COUNTER_SPILLOVER_RESTING, COUNTER_WOKE_DEFERRED,
};
use dynamis_sort::RadixSort;
pub(super) struct Commit {
thaw_contacts: Stage,
freeze_contacts: Stage,
resting_gather: Stage,
resting_commit: Stage,
contact_archive: Stage,
archive_count_sync: Stage,
static_wake_clear: Stage,
query: Stage,
}
impl Commit {
pub(super) fn build(context: &GpuContext, buffers: &WorldBuffers, per_row: u32) -> Self {
Self {
thaw_contacts: Stage::build(
context,
"thaw_contacts",
include_str!("shaders/thaw_contacts.wgsl"),
per_row,
CONTACT,
&[
(RO, whole(&buffers.contacts.resting)),
(RW, whole(&buffers.contacts.resting_live)),
(RW, whole(&buffers.contacts.resting_next)),
(RW, whole(&buffers.contacts.resting_free)),
(RW, buffers.counter(COUNTER_RESTING)),
(RO, whole(&buffers.bodies.states)),
(RO, whole(&buffers.bodies.rows)),
(RO, whole(&buffers.bodies.activity)),
(RO, whole(&buffers.contacts.manifolds)),
(RW, buffers.counter(COUNTER_CONTACTS)),
(RW, whole(&buffers.events)),
(RW, buffers.counter(COUNTER_EVENTS)),
(RW, buffers.counter(COUNTER_SPILLOVER_EVENTS)),
(UNIFORM, whole(&buffers.params)),
],
&[],
),
resting_gather: Stage::build(
context,
"resting_gather",
include_str!("shaders/resting_gather.wgsl"),
per_row,
IDENTITY,
&[
(RO, whole(&buffers.contacts.resting)),
(RW, buffers.counter(COUNTER_RESTING)),
(RO, whole(&buffers.contacts.resting_live)),
(RW, whole(&buffers.contacts.resting_index.major)),
(RW, whole(&buffers.contacts.resting_index.minor)),
(RW, whole(&buffers.contacts.resting_index.payload)),
(RW, buffers.counter(COUNTER_RESTING_GATHER)),
],
&[],
),
resting_commit: Stage::build(
context,
"resting_commit",
include_str!("shaders/resting_commit.wgsl"),
per_row,
CORE,
&[
(RW, buffers.counter(COUNTER_SLEPT)),
(RW, buffers.counter(COUNTER_RESTING_GATHER)),
(RW, buffers.counter(COUNTER_RESTING_INDEX)),
(RW, buffers.counter(COUNTER_WOKE_DEFERRED)),
(RW, buffers.counter(COUNTER_RESTING_PENDING)),
],
&[],
),
freeze_contacts: Stage::build(
context,
"freeze_contacts",
include_str!("shaders/freeze_contacts.wgsl"),
per_row,
CORE,
&[
(RO, whole(&buffers.contacts.manifolds)),
(RW, buffers.counter(COUNTER_CONTACTS)),
(RO, whole(&buffers.bodies.states)),
(RW, whole(&buffers.contacts.resting)),
(RW, whole(&buffers.contacts.resting_live)),
(RW, buffers.counter(COUNTER_RESTING)),
(RW, buffers.counter(COUNTER_SPILLOVER_RESTING)),
(RO, whole(&buffers.bodies.descriptors)),
(RW, whole(&buffers.contacts.resting_next)),
(RW, whole(&buffers.contacts.resting_free)),
],
&[],
),
contact_archive: Stage::build(
context,
"contact_archive",
include_str!("shaders/contact_archive.wgsl"),
per_row,
CORE,
&[
(RO, whole(&buffers.contacts.manifolds)),
(RW, whole(&buffers.contacts.archive)),
(RW, buffers.counter(COUNTER_CONTACTS)),
],
&[],
),
archive_count_sync: Stage::build(
context,
"archive_count_sync",
include_str!("shaders/archive_count_sync.wgsl"),
per_row,
CORE,
&[
(RW, buffers.counter(COUNTER_CONTACTS)),
(RW, buffers.counter(COUNTER_ARCHIVED)),
(RO, whole(&buffers.contacts.manifolds)),
],
&[],
),
static_wake_clear: Stage::build(
context,
"static_wake_clear",
include_str!("shaders/static_wake_clear.wgsl"),
per_row,
CORE,
&[
(UNIFORM, whole(&buffers.params)),
(RW, whole(&buffers.islands.wake_flags)),
],
&[],
),
query: Stage::build(
context,
"query",
include_str!("shaders/queries.wgsl"),
per_row,
GEOMETRY,
&[
(RO, whole(&buffers.queries.records)),
(RO, whole(&buffers.bodies.states)),
(RO, whole(&buffers.bodies.descriptors)),
(RO, whole(&buffers.bodies.colliders)),
(RO, whole(&buffers.bodies.aabbs)),
(RO, whole(&buffers.contacts.entries.cells)),
(RO, whole(&buffers.contacts.entries.colliders)),
(RW, buffers.counter(COUNTER_ENTRIES)),
(RW, whole(&buffers.queries.results)),
(RO, whole(&buffers.contacts.large_bodies)),
(RW, buffers.counter(COUNTER_LARGE)),
(UNIFORM, whole(&buffers.params)),
],
&shape_resources(buffers),
),
}
}
pub(super) fn record_query(&self, recorder: &mut ComputeRecorder, query_count: u32) {
self.query.record_workgroups(recorder, query_count);
}
pub(super) fn record(
&self,
recorder: &mut ComputeRecorder,
buffers: &WorldBuffers,
params: &FrameParams,
) {
self.thaw_contacts
.record_indirect(recorder, &buffers.dispatch, THAW_CONTACTS);
self.contact_archive
.record_indirect(recorder, &buffers.dispatch, CONTACT_ARCHIVE);
self.archive_count_sync.record_workgroups(recorder, 1);
self.static_wake_clear.record(recorder, params.body_count);
self.freeze_contacts
.record_indirect(recorder, &buffers.dispatch, FREEZE_CONTACTS);
if params.query_count > 0 {
self.record_query(recorder, params.query_count);
}
}
pub(super) fn record_gather(&self, recorder: &mut ComputeRecorder, buffers: &WorldBuffers) {
self.resting_gather
.record_indirect(recorder, &buffers.dispatch, RESTING_GATHER);
}
pub(super) fn record_index(
&self,
recorder: &mut ComputeRecorder,
buffers: &WorldBuffers,
sort: &RadixSort,
) {
self.resting_commit.record_workgroups(recorder, 1);
let words = buffers.collider_words();
let channels = buffers.sort_keyed(
buffers.counter(COUNTER_RESTING_GATHER),
&buffers.contacts.resting_index.major,
&buffers.contacts.resting_index.minor,
&buffers.contacts.resting_index.payload,
);
sort.sort(
recorder,
&channels,
words,
words,
&buffers.dispatch,
SORT_RESTING,
);
}
}