MCPcopy Create free account
hub / github.com/FlaxEngine/FlaxEngine / Sort

Method Sort

Source/Engine/Renderer/Utils/BitonicSort.cpp:79–145  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

77}
78
79void BitonicSort::Sort(GPUContext* context, GPUBuffer* indicesBuffer, GPUBuffer* keysBuffer, GPUBuffer* countBuffer, uint32 counterOffset, bool sortAscending, int32 maxElements)
80{
81 ASSERT(context && indicesBuffer && keysBuffer && countBuffer);
82 if (checkIfSkipPass())
83 return;
84 PROFILE_GPU_CPU("Bitonic Sort");
85 int32 maxNumElements = (int32)indicesBuffer->GetElementsCount();
86 if (maxElements > 0 && maxElements < maxNumElements)
87 maxNumElements = maxElements;
88 const uint32 alignedMaxNumElements = Math::RoundUpToPowerOf2(maxNumElements);
89 const uint32 maxIterations = (uint32)Math::Log2((float)Math::Max(2048u, alignedMaxNumElements)) - 10;
90
91 // Setup constants buffer
92 Data data;
93 data.CounterOffset = counterOffset;
94 data.NullItemKey = sortAscending ? MAX_float : -MAX_float;
95 data.NullItemIndex = 0;
96 data.KeySign = sortAscending ? -1.0f : 1.0f;
97 data.MaxIterations = maxIterations;
98 data.LoopK = 0;
99 data.LoopJ = 0;
100 context->UpdateCB(_cb, &data);
101 context->BindCB(0, _cb);
102 context->BindSR(0, countBuffer->View());
103
104 // If item count is small we can do only presorting within a single dispatch thread group
105 if (maxNumElements <= 2048)
106 {
107 // Use pre-sort with smaller thread group size (eg. for small particle emitters sorting)
108 const int32 permutation = maxNumElements < 128 ? 1 : 0;
109 context->BindUA(0, indicesBuffer->View());
110 context->BindUA(1, keysBuffer->View());
111 context->Dispatch(_preSortCS.Get(permutation), 1, 1, 1);
112 }
113 else
114 {
115 // Generate execute indirect arguments
116 context->BindUA(0, _dispatchArgsBuffer->View());
117 context->Dispatch(_indirectArgsCS, 1, 1, 1);
118
119 // Pre-Sort the buffer up to k = 2048 (this also pads the list with invalid indices that will drift to the end of the sorted list)
120 context->BindUA(0, indicesBuffer->View());
121 context->BindUA(1, keysBuffer->View());
122 context->DispatchIndirect(_preSortCS.Get(0), _dispatchArgsBuffer, 0);
123
124 // We have already pre-sorted up through k = 2048 when first writing our list, so we continue sorting with k = 4096
125 // For really large values of k, these indirect dispatches will be skipped over with thread counts of 0
126 uint32 indirectArgsOffset = sizeof(GPUDispatchIndirectArgs);
127 for (uint32 k = 4096; k <= alignedMaxNumElements; k *= 2)
128 {
129 for (uint32 j = k / 2; j >= 2048; j /= 2)
130 {
131 data.LoopK = k;
132 data.LoopJ = j;
133 context->UpdateCB(_cb, &data);
134
135 context->DispatchIndirect(_outerSortCS, _dispatchArgsBuffer, indirectArgsOffset);
136 indirectArgsOffset += sizeof(GPUDispatchIndirectArgs);

Callers

nothing calls this directly

Calls 12

RoundUpToPowerOf2Function · 0.50
Log2Function · 0.50
MaxFunction · 0.50
UpdateCBMethod · 0.45
BindCBMethod · 0.45
BindSRMethod · 0.45
ViewMethod · 0.45
BindUAMethod · 0.45
DispatchMethod · 0.45
GetMethod · 0.45
DispatchIndirectMethod · 0.45
ResetUAMethod · 0.45

Tested by

no test coverage detected