Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src_rbd/broad_phase/narrow_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl GpuNarrowPhase {
batch_indices: &Tensor<crate::shaders::utils::BatchIndices>,
collider_parent: &Tensor<u32>,
collider_materials: &Tensor<crate::shaders::queries::ColliderMaterial>,
prediction: &Tensor<f32>,
) -> Result<(), GpuBackendError> {
let num_batches = contacts_len.len() as u32;
self.reset_narrow_phase
Expand All @@ -65,6 +66,7 @@ impl GpuNarrowPhase {
batch_indices,
collider_parent,
collider_materials,
prediction,
)?;

// Pass 2: defer the complex shape pairs into `pfm_pairs` (kept as a
Expand All @@ -79,6 +81,7 @@ impl GpuNarrowPhase {
pfm_pairs,
pfm_pairs_len,
batch_indices,
prediction,
vertices,
indices,
)?;
Expand All @@ -97,6 +100,7 @@ impl GpuNarrowPhase {
indices,
collider_parent,
collider_materials,
prediction,
)?;
self.init_contacts_indirect_args
.call(pass, 1u32, contacts_len, contacts_indirect)?;
Expand Down
7 changes: 7 additions & 0 deletions src_rbd/pipeline/insertion_removal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ impl RbdState {
BufferUsages::STORAGE | BufferUsages::UNIFORM,
)
.unwrap();
let prediction = Tensor::scalar(
backend,
all_sim_params[0].prediction_distance(),
BufferUsages::UNIFORM | BufferUsages::COPY_DST,
)
.unwrap();
// Two-element readback: the (max) collision-pair count and the uncolored count.
let resize_readback = GpuReadback::new(backend, 2).unwrap();
let collision_pairs_indirect =
Expand Down Expand Up @@ -250,6 +256,7 @@ impl RbdState {
collision_pairs_len,
collision_pairs_len_max,
num_batches_uniform,
prediction,
resize_readback,
collision_pairs_indirect,
contacts_per_batch_cpu,
Expand Down
3 changes: 3 additions & 0 deletions src_rbd/pipeline/rbd_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ pub struct RbdState {
/// Single-element scratch holding the max of `collision_pairs_len` across all
/// batches, computed on the GPU (only used when `num_batches > 1`).
pub(super) collision_pairs_len_max: Tensor<u32>,
/// Contact prediction distance (`RbdSimParams::prediction_distance`),
/// consumed by the narrow-phase kernels.
pub(super) prediction: Tensor<f32>,
/// `num_batches` as a uniform, the scan length for the max reduction.
pub(super) num_batches_uniform: Tensor<TensorShape>,
/// Non-blocking readback of `[max collision_pairs_len, uncolored]` used by
Expand Down
7 changes: 7 additions & 0 deletions src_rbd/pipeline/rbd_state_from_rapier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,12 @@ impl RbdState {
BufferUsages::STORAGE | BufferUsages::UNIFORM,
)
.unwrap();
let prediction = Tensor::scalar(
backend,
all_sim_params[0].prediction_distance(),
BufferUsages::UNIFORM | BufferUsages::COPY_DST,
)
.unwrap();
// Two-element readback: the (max) collision-pair count and the uncolored count.
let resize_readback = GpuReadback::new(backend, 2).unwrap();
let collision_pairs_indirect =
Expand Down Expand Up @@ -741,6 +747,7 @@ impl RbdState {
collision_pairs_len,
collision_pairs_len_max,
num_batches_uniform,
prediction,
resize_readback,
collision_pairs_indirect,
contacts_per_batch_cpu,
Expand Down
1 change: 1 addition & 0 deletions src_rbd/pipeline/rbd_step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ impl RbdPipeline {
&state.batch_indices,
&state.collider_parent,
&state.collider_materials,
&state.prediction,
)?;

drop(pass);
Expand Down
32 changes: 20 additions & 12 deletions src_rbd_shaders/broad_phase/narrow_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ pub fn gpu_narrow_phase_init_contacts_dispatch(
*indirect_args.at_mut(2) = 1;
}

const PREDICTION: f32 = 2.0e-3; // TODO: make the prediction configurable.

/// Narrow phase, pass 1 of 2: analytic shape-shape contacts for ball / cuboid
/// pairs, written straight into the `contacts` buffer.
///
Expand All @@ -95,6 +93,8 @@ pub fn gpu_narrow_phase_shape_shape(
#[spirv(storage_buffer, descriptor_set = 0, binding = 7)] collider_parent: &[u32],
#[spirv(storage_buffer, descriptor_set = 0, binding = 8)]
collider_materials: &[ColliderMaterial],
// Contact prediction distance (`RbdSimParams::prediction_distance`).
#[spirv(uniform, descriptor_set = 0, binding = 9)] prediction: &f32,
) {
let num_threads = num_workgroups.x * WORKGROUP_SIZE;
let batch_id = invocation_id.y;
Expand Down Expand Up @@ -162,12 +162,12 @@ pub fn gpu_narrow_phase_shape_shape(
if shape_ty1 == SHAPE_TYPE_CUBOID && shape_ty2 == SHAPE_TYPE_CUBOID {
let cuboid1 = shape1.to_cuboid();
let cuboid2 = shape2.to_cuboid();
manifold = cuboid_cuboid(pose12, &cuboid1, &cuboid2, PREDICTION);
manifold = cuboid_cuboid(pose12, &cuboid1, &cuboid2, *prediction);
}

// Everything else (PFM / trimesh / polyline) is handled by the deferred
// pass; `manifold.len` stays 0 here so nothing is written.
if manifold.len > 0 && manifold.points_a.at(0).dist < PREDICTION {
if manifold.len > 0 && manifold.points_a.at(0).dist < *prediction {
let target_contact_index = atomic_add_u32(contacts_len, 1) as usize;

// NOTE: if we exceed the contacts allocation size, just skip
Expand Down Expand Up @@ -212,6 +212,7 @@ pub fn gpu_narrow_phase_shape_shape_deferred(
// And we assume all batch dimensions are given the same buffer allocation sizes
// (i.e. the same `contacts_batch_capacity`).
#[spirv(uniform, descriptor_set = 0, binding = 6)] batch_ids: &BatchIndices,
#[spirv(uniform, descriptor_set = 0, binding = 7)] prediction: &f32,
) {
let num_threads = num_workgroups.x * WORKGROUP_SIZE;
let batch_id = invocation_id.y;
Expand Down Expand Up @@ -296,6 +297,7 @@ pub fn gpu_narrow_phase_shape_shape_deferred(
let mesh = shape1.to_trimesh();
let convex = shape2;
trimesh_convex(
*prediction,
pose12,
&mesh,
convex,
Expand All @@ -313,6 +315,7 @@ pub fn gpu_narrow_phase_shape_shape_deferred(
let mesh = shape2.to_trimesh();
// NOTE: pair indices are flipped.
trimesh_convex(
*prediction,
pose12.inverse(),
&mesh,
convex,
Expand All @@ -331,6 +334,7 @@ pub fn gpu_narrow_phase_shape_shape_deferred(
let pline = shape1.to_polyline();
let convex = shape2;
polyline_convex(
*prediction,
pose12,
&pline,
convex,
Expand All @@ -348,6 +352,7 @@ pub fn gpu_narrow_phase_shape_shape_deferred(
let pline = shape2.to_polyline();
// NOTE: pair indices are flipped.
polyline_convex(
*prediction,
pose12.inverse(),
&pline,
convex,
Expand All @@ -364,6 +369,7 @@ pub fn gpu_narrow_phase_shape_shape_deferred(

/// Collision detection between a triangle mesh and a convex shape.
fn trimesh_convex(
prediction: f32,
pose12: Pose,
mesh: &TriMesh,
convex: &Shape,
Expand All @@ -379,10 +385,10 @@ fn trimesh_convex(
return;
}

// Get the convex shape's AABB in the trimesh's local space, and enlarge with the PREDICTION.
// Get the convex shape's AABB in the trimesh's local space, and enlarge with the prediction distance.
let mut test_aabb = convex.compute_aabb(pose12, vertices);
test_aabb.mins -= Vector::splat(PREDICTION);
test_aabb.maxs += Vector::splat(PREDICTION);
test_aabb.mins -= Vector::splat(prediction);
test_aabb.maxs += Vector::splat(prediction);

if !test_aabb.intersects(&mesh.root_aabb) {
// No collision possible.
Expand Down Expand Up @@ -430,6 +436,7 @@ fn trimesh_convex(

/// Collision detection between a polyline and a convex shape.
fn polyline_convex(
prediction: f32,
pose12: Pose,
mesh: &Polyline,
convex: &Shape,
Expand All @@ -445,11 +452,11 @@ fn polyline_convex(
return;
}

// Get the convex shape's AABB in the polyline's local space, and enlarge with the PREDICTION.
// Get the convex shape's AABB in the polyline's local space, and enlarge with the prediction distance.
let thickness = 0.4; // TODO: make thickness configurable or part of the polyline struct
let mut test_aabb = convex.compute_aabb(pose12, vertices);
test_aabb.mins -= Vector::splat(PREDICTION + thickness);
test_aabb.maxs += Vector::splat(PREDICTION + thickness);
test_aabb.mins -= Vector::splat(prediction + thickness);
test_aabb.maxs += Vector::splat(prediction + thickness);

if !test_aabb.intersects(&mesh.root_aabb) {
// No collision possible.
Expand Down Expand Up @@ -555,6 +562,7 @@ pub fn gpu_narrow_phase_pfm_pfm(
#[spirv(storage_buffer, descriptor_set = 0, binding = 7)] collider_parent: &[u32],
#[spirv(storage_buffer, descriptor_set = 0, binding = 8)]
collider_materials: &[ColliderMaterial],
#[spirv(uniform, descriptor_set = 0, binding = 9)] prediction: &f32,
) {
let num_threads = num_workgroups.x * WORKGROUP_SIZE;
let batch_id = invocation_id.y;
Expand Down Expand Up @@ -583,13 +591,13 @@ pub fn gpu_narrow_phase_pfm_pfm(
pair.thickness1,
&pair.shape2,
pair.thickness2,
PREDICTION,
*prediction,
vertices,
#[cfg(feature = "dim3")]
indices,
);

if manifold.len > 0 && manifold.points_a.at(0).dist < PREDICTION {
if manifold.len > 0 && manifold.points_a.at(0).dist < *prediction {
let target_contact_index = atomic_add_u32(contacts_len, 1) as usize;

// NOTE: if we exceed the contacts allocation size, just skip
Expand Down
Loading