diff --git a/Source/Engine/Core/Collections/Sorting.h b/Source/Engine/Core/Collections/Sorting.h index c6ae99b13..171c855a3 100644 --- a/Source/Engine/Core/Collections/Sorting.h +++ b/Source/Engine/Core/Collections/Sorting.h @@ -44,6 +44,49 @@ public: } }; +private: + template + static void Merge(T* data, T* tmp, int32 start, int32 mid, int32 end) + { + int32 h = start; + int32 i = start; + int32 j = mid + 1; + + while (h <= mid && j <= end) + { + if (data[h] < data[j]) + tmp[i] = data[h++]; + else + tmp[i] = data[j++]; + i++; + } + + if (h > mid) + { + for (int32 k = j; k <= end; k++) + tmp[i++] = data[k]; + } + else + { + for (int32 k = h; k <= mid; k++) + tmp[i++] = data[k]; + } + + for (int32 k = start; k <= end; k++) + data[k] = tmp[k]; + } + + template + static void MergeSort(T* data, T* tmp, int32 start, int32 end) + { + if (start >= end) + return; + const int32 mid = (start + end) / 2; + MergeSort(data, tmp, start, mid); + MergeSort(data, tmp, mid + 1, end); + Merge(data, tmp, start, mid, end); + } + public: /// /// Sorts the linear data array using Quick Sort algorithm (non recursive version, uses temporary stack collection). @@ -263,6 +306,33 @@ public: } } + /// + /// Sorts the linear data array using Merge Sort algorithm (recursive version, uses temporary memory). + /// + /// The data pointer. + /// The elements count. + /// The additional temporary memory buffer for sorting data. If null then will be automatically allocated within this function call. + template + static void MergeSort(T* data, int32 count, T* tmp = nullptr) + { + if (count < 2) + return; + const bool alloc = tmp == nullptr; + if (alloc) + tmp = (T*)Platform::Allocate(sizeof(T) * count, 16); + MergeSort(data, tmp, 0, count - 1); + if (alloc) + Platform::Free(tmp); + } + + template + FORCE_INLINE static void MergeSort(Array& data, Array* tmp = nullptr) + { + if (tmp) + tmp->Resize(data.Count()); + MergeSort(data.Get(), data.Count(), tmp ? tmp->Get() : nullptr); + } + /// /// Sorts the linear data array using Radix Sort algorithm (uses temporary keys collection). /// diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index a8a4ae73b..2fa1b98ca 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -27,6 +27,7 @@ namespace // Cached data for the draw calls sorting Array SortingKeys[2]; Array SortingIndices; + Array SortingBatches; Array FreeRenderList; struct MemPoolEntry @@ -638,7 +639,7 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD } // Sort draw calls batches by depth - Sorting::QuickSort(list.Batches); + Sorting::MergeSort(list.Batches, &SortingBatches); } FORCE_INLINE bool CanUseInstancing(DrawPass pass)