void sort(Itr begin, Itr end) { _shuffle(begin, end); _sort(begin, end); _insertion_sort(begin, end); }
void _sort_rects(DArray rects_in) { assert(rects_in.size > 1); // Insertion sort for small buffers if(rects_in.size <= 8) { _insertion_sort(rects_in); return; } // Assure out buffer is big enough rects_out.size = 0; if(rects_out.reserved < rects_in.size) darray_reserve(&rects_out, MAX(rects_in.size, rects_out.reserved*2)); assert(rects_out.reserved >= rects_in.size); assert(rects_out.item_size == rects_in.item_size); TexturedRectDesc* r_in = DARRAY_DATA_PTR(rects_in, TexturedRectDesc); TexturedRectDesc* r_out = DARRAY_DATA_PTR(rects_out, TexturedRectDesc); uint i, unique_textures = 0, switches = 0; memset(radix_counts, 0, sizeof(radix_counts)); // If there is more than 255 textures our simple count sort won't work assert(textures.size < 256); // Calculate histogram, unsorted texture switches, unique textures for(i = 0; i < rects_in.size; ++i) { size_t idx = r_in[i].tex & 0xFF; radix_counts[idx]++; if (radix_counts[idx] == 1) unique_textures++; if(i > 0 && r_in[i].tex != r_in[i-1].tex) switches++; } // Don't bother sorting if it wouldn't decrease batch count if(unique_textures < 3 || unique_textures == switches) return; // Convert histogram to start indices for(i = 1; i < 256; ++i) radix_counts[i] = radix_counts[i-1] + radix_counts[i]; // Count sort (single pass of radix sort - texture amount is not a large // number) uint r0 = 0; for(i = 0; i < rects_in.size; ++i) { size_t idx = r_in[i].tex & 0xFF; uint* dest = idx ? &radix_counts[idx-1] : &r0; r_out[(*dest)++] = r_in[i]; } memcpy(r_in, r_out, rects_in.size * rects_in.item_size); }