Revision control

++ // Copyright 2009-2021 Intel Corporation
++ // SPDX-License-Identifier: Apache-2.0
++
++ #pragma once
++
++ #include "default.h"
++
++ namespace embree
++ {
++ /*! An item on the stack holds the node ID and distance of that node. */
++ template<typename T>
++ struct __aligned(16) StackItemT
++ {
++ /*! assert that the xchg function works */
++ static_assert(sizeof(T) <= 12, "sizeof(T) <= 12 failed");
++
++ __forceinline StackItemT() {}
++
++ __forceinline StackItemT(T &ptr, unsigned &dist) : ptr(ptr), dist(dist) {}
++
++ /*! use SSE instructions to swap stack items */
++ __forceinline static void xchg(StackItemT& a, StackItemT& b)
++ {
++ const vfloat4 sse_a = vfloat4::load((float*)&a);
++ const vfloat4 sse_b = vfloat4::load((float*)&b);
++ vfloat4::store(&a,sse_b);
++ vfloat4::store(&b,sse_a);
++ }
++
++ /*! Sort 2 stack items. */
++ __forceinline friend void sort(StackItemT& s1, StackItemT& s2) {
++ if (s2.dist < s1.dist) xchg(s2,s1);
++ }
++
++ /*! Sort 3 stack items. */
++ __forceinline friend void sort(StackItemT& s1, StackItemT& s2, StackItemT& s3)
++ {
++ if (s2.dist < s1.dist) xchg(s2,s1);
++ if (s3.dist < s2.dist) xchg(s3,s2);
++ if (s2.dist < s1.dist) xchg(s2,s1);
++ }
++
++ /*! Sort 4 stack items. */
++ __forceinline friend void sort(StackItemT& s1, StackItemT& s2, StackItemT& s3, StackItemT& s4)
++ {
++ if (s2.dist < s1.dist) xchg(s2,s1);
++ if (s4.dist < s3.dist) xchg(s4,s3);
++ if (s3.dist < s1.dist) xchg(s3,s1);
++ if (s4.dist < s2.dist) xchg(s4,s2);
++ if (s3.dist < s2.dist) xchg(s3,s2);
++ }
++
++ /*! use SSE instructions to swap stack items */
++ __forceinline static void cmp_xchg(vint4& a, vint4& b)
++ {
++ #if defined(__AVX512VL__)
++ const vboolf4 mask(shuffle<2,2,2,2>(b) < shuffle<2,2,2,2>(a));
++ #else
++ const vboolf4 mask0(b < a);
++ const vboolf4 mask(shuffle<2,2,2,2>(mask0));
++ #endif
++ const vint4 c = select(mask,b,a);
++ const vint4 d = select(mask,a,b);
++ a = c;
++ b = d;
++ }
++
++ /*! Sort 3 stack items. */
++ __forceinline static void sort3(vint4& s1, vint4& s2, vint4& s3)
++ {
++ cmp_xchg(s2,s1);
++ cmp_xchg(s3,s2);
++ cmp_xchg(s2,s1);
++ }
++
++ /*! Sort 4 stack items. */
++ __forceinline static void sort4(vint4& s1, vint4& s2, vint4& s3, vint4& s4)
++ {
++ cmp_xchg(s2,s1);
++ cmp_xchg(s4,s3);
++ cmp_xchg(s3,s1);
++ cmp_xchg(s4,s2);
++ cmp_xchg(s3,s2);
++ }
++
++
++ /*! Sort N stack items. */
++ __forceinline friend void sort(StackItemT* begin, StackItemT* end)
++ {
++ for (StackItemT* i = begin+1; i != end; ++i)
++ {
++ const vfloat4 item = vfloat4::load((float*)i);
++ const unsigned dist = i->dist;
++ StackItemT* j = i;
++
++ while ((j != begin) && ((j-1)->dist < dist))
++ {
++ vfloat4::store(j, vfloat4::load((float*)(j-1)));
++ --j;
++ }
++
++ vfloat4::store(j, item);
++ }
++ }
++
++ public:
++ T ptr;
++ unsigned dist;
++ };
++
++ /*! An item on the stack holds the node ID and active ray mask. */
++ template<typename T>
++ struct __aligned(8) StackItemMaskT
++ {
++ T ptr;
++ size_t mask;
++ };
++
++ struct __aligned(8) StackItemMaskCoherent
++ {
++ size_t mask;
++ size_t parent;
++ size_t child;
++ };
++ }