14 #include "smmintrin.h"
16 #include <forward_list>
22 #ifdef POINTER_IS_64BIT
24 # define LOAD_128 _mm_load_si128
26 # define LOAD_128 _mm_loadu_si128
30 void ViewportSortParentSpritesSSE41(ParentSpriteToSortVector *psdv)
32 if (psdv->size() < 2)
return;
34 const __m128i mask_ptest = _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0);
43 const uint32 ORDER_COMPARED = UINT32_MAX;
44 const uint32 ORDER_RETURNED = UINT32_MAX - 1;
45 std::stack<ParentSpriteToDraw *> sprite_order;
46 uint32 next_order = 0;
48 std::forward_list<std::pair<int64, ParentSpriteToDraw *>> sprite_list;
51 for (
auto p = psdv->rbegin(); p != psdv->rend(); p++) {
52 sprite_list.push_front(std::make_pair((*p)->xmin + (*p)->ymin, *p));
53 sprite_order.push(*p);
54 (*p)->order = next_order++;
59 std::vector<ParentSpriteToDraw *> preceding;
60 auto preceding_prev = sprite_list.begin();
61 auto out = psdv->begin();
63 while (!sprite_order.empty()) {
65 auto s = sprite_order.top();
69 if (s->order == ORDER_RETURNED)
continue;
72 if (s->order == ORDER_COMPARED) {
74 s->order = ORDER_RETURNED;
88 auto ssum = std::max(s->xmax, s->xmin) + std::max(s->ymax, s->ymin);
89 auto prev = sprite_list.before_begin();
90 auto x = sprite_list.begin();
91 while (x != sprite_list.end() && ((*x).first <= ssum)) {
95 x = sprite_list.erase_after(prev);
103 __m128i s_max = LOAD_128((__m128i*) &s->xmax);
104 __m128i p_min = LOAD_128((__m128i*) &p->xmin);
105 __m128i r1 = _mm_cmplt_epi32(s_max, p_min);
106 if (!_mm_testz_si128(mask_ptest, r1))
112 __m128i s_min = LOAD_128((__m128i*) &s->xmin);
113 __m128i p_max = LOAD_128((__m128i*) &p->xmax);
114 __m128i r2 = _mm_cmplt_epi32(p_max, s_min);
115 if (_mm_testz_si128(mask_ptest, r2)) {
122 if (s->xmin + s->xmax + s->ymin + s->ymax + s->zmin + s->zmax <=
123 p->xmin + p->xmax + p->ymin + p->ymax + p->zmin + p->zmax) {
128 preceding.push_back(p);
129 preceding_prev = p_prev;
132 if (preceding.empty()) {
135 s->order = ORDER_RETURNED;
140 if (preceding.size() == 1) {
141 auto p = preceding[0];
143 if (p->xmax <= s->xmax && p->ymax <= s->ymax && p->zmax <= s->zmax) {
144 p->order = ORDER_RETURNED;
145 s->order = ORDER_RETURNED;
146 sprite_list.erase_after(preceding_prev);
155 return a->order > b->order;
158 s->order = ORDER_COMPARED;
159 sprite_order.push(s);
161 for (
auto p: preceding) {
162 p->order = next_order++;
163 sprite_order.push(p);
173 bool ViewportSortParentSpritesSSE41Checker()