private void ComputeGridHash() { // Clear cells int kernel = 0; int numBlocks = (int)ComputeGroupSize(simulationParameters[0].numCells, BLOCK_SIZE); computeGridShader.SetBuffer(kernel, "cells_rw", bufCells); computeGridShader.Dispatch(kernel, numBlocks, 1, 1); // Compute (hash, index) kernel = 1; numBlocks = (int)ComputeGroupSize((uint)simulationParameters[0].maxParticles, BLOCK_SIZE); computeGridShader.SetBuffer(kernel, "parameters", bufSimulationParameters); computeGridShader.SetBuffer(kernel, "pos_press", bufPosPress[0]); computeGridShader.SetBuffer(kernel, "vel_rho", bufVelRho[0]); computeGridShader.SetBuffer(kernel, "force_vol", bufForceVol[0]); computeGridShader.SetBuffer(kernel, "tgrm", bufTGRM[0]); computeGridShader.SetBuffer(kernel, "sort_data_rw", bufSortData[0]); computeGridShader.Dispatch(kernel, numBlocks, 1, 1); // Sort (hash-index) using bitonic sort int roundUpPowerOf2 = (int)Mathf.Pow(2, Mathf.Ceil(Mathf.Log(simulationParameters[0].maxParticles) / Mathf.Log(2.0f))); bitonicSort.BitonicSort(bufSortData[0], bufSortData[1], (uint)roundUpPowerOf2); // Reorder particle data and compute cell data kernel = 2; numBlocks = (int)ComputeGroupSize((uint)simulationParameters[0].numParticles, BLOCK_SIZE); computeGridShader.SetBuffer(kernel, "parameters", bufSimulationParameters); computeGridShader.SetBuffer(kernel, "pos_press", bufPosPress[0]); computeGridShader.SetBuffer(kernel, "vel_rho", bufVelRho[0]); computeGridShader.SetBuffer(kernel, "force_vol", bufForceVol[0]); computeGridShader.SetBuffer(kernel, "tgrm", bufTGRM[0]); computeGridShader.SetBuffer(kernel, "pos_press_rw", bufPosPress[1]); computeGridShader.SetBuffer(kernel, "vel_rho_rw", bufVelRho[1]); computeGridShader.SetBuffer(kernel, "force_vol_rw", bufForceVol[1]); computeGridShader.SetBuffer(kernel, "tgrm_rw", bufTGRM[1]); computeGridShader.SetBuffer(kernel, "sort_data", bufSortData[0]); computeGridShader.SetBuffer(kernel, "cells_rw", bufCells); computeGridShader.Dispatch(kernel, numBlocks, 1, 1); }
void Update() { if (s_update_count++ == 0) { GPUParticleEmitter.UpdateAll(); GPUParticleForce.UpdateAll(); GPUParticleColliderBase.UpdateAll(); } m_world_data[0].timestep = Time.deltaTime * 0.6f; m_world_data[0].particle_size = m_particle_radius; m_world_data[0].particle_lifetime = m_lifetime; m_world_data[0].num_sphere_colliders = m_sphere_colliders.Count; m_world_data[0].num_capsule_colliders = m_capsule_colliders.Count; m_world_data[0].num_box_colliders = m_box_colliders.Count; m_world_data[0].num_forces = m_forces.Count; m_world_data[0].damping = m_damping; m_world_data[0].advection = m_advection; m_world_data[0].coord_scaler = m_coord_scaler; m_world_data[0].pressure_stiffness = m_pressure_stiffness; m_world_data[0].wall_stiffness = m_wall_stiffness; m_sph_params[0].smooth_len = m_sph_smoothlen; m_sph_params[0].particle_mass = m_sph_particleMass; m_sph_params[0].pressure_stiffness = m_sph_pressureStiffness; m_sph_params[0].rest_density = m_sph_restDensity; m_sph_params[0].viscosity = m_sph_viscosity; m_buf_sphere_colliders.SetData(m_sphere_colliders.ToArray()); m_sphere_colliders.Clear(); m_buf_capsule_colliders.SetData(m_capsule_colliders.ToArray()); m_capsule_colliders.Clear(); m_buf_box_colliders.SetData(m_box_colliders.ToArray()); m_box_colliders.Clear(); m_buf_forces.SetData(m_forces.ToArray()); m_forces.Clear(); IVector3 world_div = m_world_data[0].world_div; int num_cells = world_div.x * world_div.y * world_div.z; m_world_data[0].num_additional_particles = m_particles_to_add.Count; m_buf_world_data.SetData(m_world_data); CSWorldData csWorldData = m_world_data[0]; m_buf_sph_params.SetData(m_sph_params); // add new particles if (m_particles_to_add.Count > 0) { ComputeShader cs = m_cs_core; int kernel = kAddParticles; m_buf_particles_to_add.SetData(m_particles_to_add.ToArray()); cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "world_idata", m_buf_world_idata); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "particles_to_add", m_buf_particles_to_add); cs.Dispatch(kernel, m_particles_to_add.Count / BLOCK_SIZE + 1, 1, 1); m_particles_to_add.Clear(); } { // clear cells { ComputeShader cs = m_cs_hashgrid; int kernel = 0; cs.SetBuffer(kernel, "cells_rw", m_buf_cells); cs.Dispatch(kernel, num_cells / BLOCK_SIZE, 1, 1); } // generate hashes { ComputeShader cs = m_cs_hashgrid; int kernel = 1; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "world_idata", m_buf_world_idata); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "sort_keys_rw", m_buf_sort_data[0]); cs.Dispatch(kernel, m_max_particles / BLOCK_SIZE, 1, 1); } // sort keys { m_bitonic_sort.BitonicSort(m_buf_sort_data[0], m_buf_sort_data[1], (uint)csWorldData.num_max_particles); } // reorder particles { ComputeShader cs = m_cs_hashgrid; int kernel = 2; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "world_idata", m_buf_world_idata); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "particles_rw", m_buf_particles[1]); cs.SetBuffer(kernel, "sort_keys", m_buf_sort_data[0]); cs.SetBuffer(kernel, "cells_rw", m_buf_cells); cs.Dispatch(kernel, m_max_particles / BLOCK_SIZE, 1, 1); GPUParticleUtils.Swap(ref m_buf_particles[0], ref m_buf_particles[1]); } } //{ // dbgSortData = new GPUSort.KIP[csWorldData.num_max_particles]; // cbSortData[0].GetData(dbgSortData); // uint prev = 0; // for (int i = 0; i < dbgSortData.Length; ++i) // { // if (prev > dbgSortData[i].key) // { // Debug.Log("sort bug: "+i); // break; // } // prev = dbgSortData[i].key; // } //} //dbgCellData = new CellData[num_cells]; //cbCells.GetData(dbgCellData); //for (int i = 0; i < num_cells; ++i ) //{ // if (dbgCellData[i].begin!=0) // { // Debug.Log("dbgCellData:" + dbgCellData[i].begin + "," + dbgCellData[i].end); // break; // } //} int num_active_blocks = m_max_particles / BLOCK_SIZE; // initialize intermediate data { ComputeShader cs = m_cs_core; int kernel = kPrepare; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); } // particle interaction if (m_solver == GPUParticleWorld.Interaction.Impulse) { ComputeShader cs = m_cs_core; int kernel = m_dimension == GPUParticleWorld.Dimension.Dimendion3D ? kProcessInteraction_Impulse : kProcessInteraction_Impulse2D; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); } else if (m_solver == GPUParticleWorld.Interaction.SPH) { ComputeShader cs = m_cs_core; int kernel = m_dimension == GPUParticleWorld.Dimension.Dimendion3D ? kProcessInteraction_SPH_Pass1 : kProcessInteraction_SPH_Pass12D; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "sph_params", m_buf_sph_params); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); kernel = m_dimension == GPUParticleWorld.Dimension.Dimendion3D ? kProcessInteraction_SPH_Pass2 : kProcessInteraction_SPH_Pass22D; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "sph_params", m_buf_sph_params); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); } else if (m_solver == GPUParticleWorld.Interaction.None) { // do nothing } //// gbuffer collision //if (m_process_gbuffer_collision) //{ // ComputeShader cs = m_cs_core; // int kernel = kProcessGBufferCollision; // cs.SetTexture(kernel, "gbuffer_normal", rtNormalBufferCopy); // cs.SetTexture(kernel, "gbuffer_position", rtPositionBufferCopy); // cs.SetBuffer(kernel, "world_data", m_buf_world_data); // cs.SetBuffer(kernel, "particles", m_buf_particles[0]); // cs.SetBuffer(kernel, "pimd", m_buf_imd); // cs.Dispatch(kernel, num_active_blocks, 1, 1); //} // colliders if (m_process_colliders) { ComputeShader cs = m_cs_core; int kernel = kProcessColliders; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.SetBuffer(kernel, "sphere_colliders", m_buf_sphere_colliders); cs.SetBuffer(kernel, "capsule_colliders", m_buf_capsule_colliders); cs.SetBuffer(kernel, "box_colliders", m_buf_box_colliders); cs.Dispatch(kernel, num_active_blocks, 1, 1); } // forces if (m_process_forces) { ComputeShader cs = m_cs_core; int kernel = kProcessForces; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.SetBuffer(kernel, "forces", m_buf_forces); cs.Dispatch(kernel, num_active_blocks, 1, 1); } // integrate { ComputeShader cs = m_cs_core; int kernel = kIntegrate; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.Dispatch(kernel, num_active_blocks, 1, 1); } }