ParticleBinCullingCS.hlsl 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
  2. // CHECK: groupId
  3. // CHECK: flattenedThreadIdInGroup
  4. // CHECK: threadIdInGroup
  5. // CHECK: bufferLoad
  6. // CHECK: UMin
  7. // CHECK: addrspace(3)
  8. // CHECK: barrier
  9. // CHECK: UMax
  10. // CHECK: bufferStore
  11. //
  12. // Copyright (c) Microsoft. All rights reserved.
  13. // This code is licensed under the MIT License (MIT).
  14. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  15. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  16. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  17. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  18. //
  19. // Developed by Minigraph
  20. //
  21. // Author(s): James Stanard
  22. // Julia Careaga
  23. //
  24. #include "ParticleUtility.hlsli"
  25. #define THREAD_GROUP_SIZE 256
  26. StructuredBuffer<ParticleScreenData> g_VisibleParticles : register( t0 );
  27. StructuredBuffer<uint> g_LargeBinParticles : register( t1 );
  28. StructuredBuffer<uint> g_LargeBinCounters : register( t2 );
  29. RWStructuredBuffer<uint> g_BinParticles : register( u0 );
  30. RWStructuredBuffer<uint> g_BinCounters : register( u1 );
  31. groupshared uint gs_BinCounters[16];
  32. cbuffer CB : register(b0)
  33. {
  34. uint2 LogTilesPerBin;
  35. };
  36. [RootSignature(Particle_RootSig)]
  37. [numthreads(4, THREAD_GROUP_SIZE / 4, 1)]
  38. void main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID )
  39. {
  40. uint LargeBinsPerRow = (gBinsPerRow + 3) / 4;
  41. uint ParticlesPerLargeBin = MAX_PARTICLES_PER_BIN * 16;
  42. uint LargeBinIndex = Gid.y * LargeBinsPerRow + Gid.x;
  43. uint ParticleCountInLargeBin = min(g_LargeBinCounters[LargeBinIndex], ParticlesPerLargeBin);
  44. // Get the start location for particles in this bin
  45. uint LargeBinStart = LargeBinIndex * ParticlesPerLargeBin;
  46. uint2 FirstBin = Gid.xy * 4;
  47. if (GI < 16)
  48. gs_BinCounters[GI] = 0;
  49. GroupMemoryBarrierWithGroupSync();
  50. for (uint idx = GI; idx < ParticleCountInLargeBin; idx += THREAD_GROUP_SIZE)
  51. {
  52. uint SortKey = g_LargeBinParticles[LargeBinStart + idx];
  53. uint GlobalIdx = SortKey & 0x3FFFF;
  54. uint Bounds = g_VisibleParticles[GlobalIdx].Bounds;
  55. uint2 MinTile = uint2(Bounds >> 0, Bounds >> 8) & 0xFF;
  56. uint2 MaxTile = uint2(Bounds >> 16, Bounds >> 24) & 0xFF;
  57. uint2 MinBin = max(MinTile >> LogTilesPerBin, FirstBin);
  58. uint2 MaxBin = min(MaxTile >> LogTilesPerBin, FirstBin + 3);
  59. for (uint y = MinBin.y; y <= MaxBin.y; ++y)
  60. {
  61. for (uint x = MinBin.x; x <= MaxBin.x; ++x)
  62. {
  63. uint CounterIdx = (x & 3) | (y & 3) << 2;
  64. uint BinOffset = (x + y * gBinsPerRow) * MAX_PARTICLES_PER_BIN;
  65. uint AllocIdx;
  66. InterlockedAdd(gs_BinCounters[CounterIdx], 1, AllocIdx);
  67. AllocIdx = min(AllocIdx, MAX_PARTICLES_PER_BIN - 1);
  68. g_BinParticles[BinOffset + AllocIdx] = SortKey;
  69. }
  70. }
  71. }
  72. GroupMemoryBarrierWithGroupSync();
  73. if (GI < 16)
  74. {
  75. uint2 OutBin = FirstBin + GTid.xy;
  76. g_BinCounters[OutBin.x + OutBin.y * gBinsPerRow] = gs_BinCounters[GI];
  77. }
  78. }