FluidCS11_DensityCS_Grid.hlsl 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
  2. // CHECK: threadId
  3. // CHECK: bufferLoad
  4. // CHECK: FMax
  5. // CHECK: FMin
  6. // CHECK: IMax
  7. // CHECK: dot2
  8. // CHECK: bufferStore
  9. //--------------------------------------------------------------------------------------
  10. // File: FluidCS11.hlsl
  11. //
  12. // Copyright (c) Microsoft Corporation. All rights reserved.
  13. //--------------------------------------------------------------------------------------
  14. //--------------------------------------------------------------------------------------
  15. // Smoothed Particle Hydrodynamics Algorithm Based Upon:
  16. // Particle-Based Fluid Simulation for Interactive Applications
  17. // Matthias Müller
  18. //--------------------------------------------------------------------------------------
  19. //--------------------------------------------------------------------------------------
  20. // Optimized Grid Algorithm Based Upon:
  21. // Broad-Phase Collision Detection with CUDA
  22. // Scott Le Grand
  23. //--------------------------------------------------------------------------------------
  24. struct Particle
  25. {
  26. float2 position;
  27. float2 velocity;
  28. };
  29. struct ParticleForces
  30. {
  31. float2 acceleration;
  32. };
  33. struct ParticleDensity
  34. {
  35. float density;
  36. };
  37. cbuffer cbSimulationConstants : register( b0 )
  38. {
  39. uint g_iNumParticles;
  40. float g_fTimeStep;
  41. float g_fSmoothlen;
  42. float g_fPressureStiffness;
  43. float g_fRestDensity;
  44. float g_fDensityCoef;
  45. float g_fGradPressureCoef;
  46. float g_fLapViscosityCoef;
  47. float g_fWallStiffness;
  48. float4 g_vGravity;
  49. float4 g_vGridDim;
  50. float3 g_vPlanes[4];
  51. };
  52. //--------------------------------------------------------------------------------------
  53. // Fluid Simulation
  54. //--------------------------------------------------------------------------------------
  55. #define SIMULATION_BLOCK_SIZE 256
  56. //--------------------------------------------------------------------------------------
  57. // Structured Buffers
  58. //--------------------------------------------------------------------------------------
  59. RWStructuredBuffer<Particle> ParticlesRW : register( u0 );
  60. StructuredBuffer<Particle> ParticlesRO : register( t0 );
  61. RWStructuredBuffer<ParticleDensity> ParticlesDensityRW : register( u0 );
  62. StructuredBuffer<ParticleDensity> ParticlesDensityRO : register( t1 );
  63. RWStructuredBuffer<ParticleForces> ParticlesForcesRW : register( u0 );
  64. StructuredBuffer<ParticleForces> ParticlesForcesRO : register( t2 );
  65. RWStructuredBuffer<unsigned int> GridRW : register( u0 );
  66. StructuredBuffer<unsigned int> GridRO : register( t3 );
  67. RWStructuredBuffer<uint2> GridIndicesRW : register( u0 );
  68. StructuredBuffer<uint2> GridIndicesRO : register( t4 );
  69. //--------------------------------------------------------------------------------------
  70. // Grid Construction
  71. //--------------------------------------------------------------------------------------
  72. // For simplicity, this sample uses a 16-bit hash based on the grid cell and
  73. // a 16-bit particle ID to keep track of the particles while sorting
  74. // This imposes a limitation of 64K particles and 256x256 grid work
  75. // You could extended the implementation to support large scenarios by using a uint2
  76. float2 GridCalculateCell(float2 position)
  77. {
  78. return clamp(position * g_vGridDim.xy + g_vGridDim.zw, float2(0, 0), float2(255, 255));
  79. }
  80. unsigned int GridConstuctKey(uint2 xy)
  81. {
  82. // Bit pack [-----UNUSED-----][----Y---][----X---]
  83. // 16-bit 8-bit 8-bit
  84. return dot(xy.yx, uint2(256, 1));
  85. }
  86. unsigned int GridConstuctKeyValuePair(uint2 xy, uint value)
  87. {
  88. // Bit pack [----Y---][----X---][-----VALUE------]
  89. // 8-bit 8-bit 16-bit
  90. return dot(uint3(xy.yx, value), uint3(256*256*256, 256*256, 1));
  91. }
  92. unsigned int GridGetKey(unsigned int keyvaluepair)
  93. {
  94. return (keyvaluepair >> 16);
  95. }
  96. unsigned int GridGetValue(unsigned int keyvaluepair)
  97. {
  98. return (keyvaluepair & 0xFFFF);
  99. }
  100. //--------------------------------------------------------------------------------------
  101. // Density Calculation
  102. //--------------------------------------------------------------------------------------
  103. float CalculateDensity(float r_sq)
  104. {
  105. const float h_sq = g_fSmoothlen * g_fSmoothlen;
  106. // Implements this equation:
  107. // W_poly6(r, h) = 315 / (64 * pi * h^9) * (h^2 - r^2)^3
  108. // g_fDensityCoef = fParticleMass * 315.0f / (64.0f * PI * fSmoothlen^9)
  109. return g_fDensityCoef * (h_sq - r_sq) * (h_sq - r_sq) * (h_sq - r_sq);
  110. }
  111. //--------------------------------------------------------------------------------------
  112. // Optimized Grid + Sort Algorithm
  113. //--------------------------------------------------------------------------------------
  114. [numthreads(SIMULATION_BLOCK_SIZE, 1, 1)]
  115. void main( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
  116. {
  117. const unsigned int P_ID = DTid.x;
  118. const float h_sq = g_fSmoothlen * g_fSmoothlen;
  119. float2 P_position = ParticlesRO[P_ID].position;
  120. float density = 0;
  121. // Calculate the density based on neighbors from the 8 adjacent cells + current cell
  122. int2 G_XY = (int2)GridCalculateCell( P_position );
  123. for (int Y = max(G_XY.y - 1, 0) ; Y <= min(G_XY.y + 1, 255) ; Y++)
  124. {
  125. for (int X = max(G_XY.x - 1, 0) ; X <= min(G_XY.x + 1, 255) ; X++)
  126. {
  127. unsigned int G_CELL = GridConstuctKey(uint2(X, Y));
  128. uint2 G_START_END = GridIndicesRO[G_CELL];
  129. for (unsigned int N_ID = G_START_END.x ; N_ID < G_START_END.y ; N_ID++)
  130. {
  131. float2 N_position = ParticlesRO[N_ID].position;
  132. float2 diff = N_position - P_position;
  133. float r_sq = dot(diff, diff);
  134. if (r_sq < h_sq)
  135. {
  136. density += CalculateDensity(r_sq);
  137. }
  138. }
  139. }
  140. }
  141. ParticlesDensityRW[P_ID].density = density;
  142. }