// RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s // CHECK: threadId // CHECK: bufferLoad // CHECK: dot2 // CHECK: bufferStore //-------------------------------------------------------------------------------------- // File: FluidCS11.hlsl // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Smoothed Particle Hydrodynamics Algorithm Based Upon: // Particle-Based Fluid Simulation for Interactive Applications // Matthias Müller //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Optimized Grid Algorithm Based Upon: // Broad-Phase Collision Detection with CUDA // Scott Le Grand //-------------------------------------------------------------------------------------- struct Particle { float2 position; float2 velocity; }; struct ParticleForces { float2 acceleration; }; struct ParticleDensity { float density; }; cbuffer cbSimulationConstants : register( b0 ) { uint g_iNumParticles; float g_fTimeStep; float g_fSmoothlen; float g_fPressureStiffness; float g_fRestDensity; float g_fDensityCoef; float g_fGradPressureCoef; float g_fLapViscosityCoef; float g_fWallStiffness; float4 g_vGravity; float4 g_vGridDim; float3 g_vPlanes[4]; }; //-------------------------------------------------------------------------------------- // Fluid Simulation //-------------------------------------------------------------------------------------- #define SIMULATION_BLOCK_SIZE 256 //-------------------------------------------------------------------------------------- // Structured Buffers //-------------------------------------------------------------------------------------- RWStructuredBuffer ParticlesRW : register( u0 ); StructuredBuffer ParticlesRO : register( t0 ); RWStructuredBuffer ParticlesDensityRW : register( u0 ); StructuredBuffer ParticlesDensityRO : register( t1 ); RWStructuredBuffer ParticlesForcesRW : register( u0 ); StructuredBuffer ParticlesForcesRO : register( t2 ); RWStructuredBuffer GridRW : register( u0 ); StructuredBuffer GridRO : register( t3 ); RWStructuredBuffer GridIndicesRW : register( u0 ); StructuredBuffer GridIndicesRO : register( t4 ); //-------------------------------------------------------------------------------------- // Grid Construction //-------------------------------------------------------------------------------------- // For simplicity, this sample uses a 16-bit hash based on the grid cell and // a 16-bit particle ID to keep track of the particles while sorting // This imposes a limitation of 64K particles and 256x256 grid work // You could extended the implementation to support large scenarios by using a uint2 float2 GridCalculateCell(float2 position) { return clamp(position * g_vGridDim.xy + g_vGridDim.zw, float2(0, 0), float2(255, 255)); } unsigned int GridConstuctKey(uint2 xy) { // Bit pack [-----UNUSED-----][----Y---][----X---] // 16-bit 8-bit 8-bit return dot(xy.yx, uint2(256, 1)); } unsigned int GridConstuctKeyValuePair(uint2 xy, uint value) { // Bit pack [----Y---][----X---][-----VALUE------] // 8-bit 8-bit 16-bit return dot(uint3(xy.yx, value), uint3(256*256*256, 256*256, 1)); } unsigned int GridGetKey(unsigned int keyvaluepair) { return (keyvaluepair >> 16); } unsigned int GridGetValue(unsigned int keyvaluepair) { return (keyvaluepair & 0xFFFF); } //-------------------------------------------------------------------------------------- // Density Calculation //-------------------------------------------------------------------------------------- float CalculateDensity(float r_sq) { const float h_sq = g_fSmoothlen * g_fSmoothlen; // Implements this equation: // W_poly6(r, h) = 315 / (64 * pi * h^9) * (h^2 - r^2)^3 // g_fDensityCoef = fParticleMass * 315.0f / (64.0f * PI * fSmoothlen^9) return g_fDensityCoef * (h_sq - r_sq) * (h_sq - r_sq) * (h_sq - r_sq); } //-------------------------------------------------------------------------------------- // Simple N^2 Algorithm //-------------------------------------------------------------------------------------- [numthreads(SIMULATION_BLOCK_SIZE, 1, 1)] void main( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) { const unsigned int P_ID = DTid.x; const float h_sq = g_fSmoothlen * g_fSmoothlen; float2 P_position = ParticlesRO[P_ID].position; float density = 0; // Calculate the density based on all neighbors for (uint N_ID = 0 ; N_ID < g_iNumParticles ; N_ID++) { float2 N_position = ParticlesRO[N_ID].position; float2 diff = N_position - P_position; float r_sq = dot(diff, diff); if (r_sq < h_sq) { density += CalculateDensity(r_sq); } } ParticlesDensityRW[P_ID].density = density; }