Advertisement
Zgragselus

KD Traversal

Apr 11th, 2021
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.84 KB | None | 0 0
  1. struct KDNode
  2. {
  3.     union
  4.     {
  5.         float split;
  6.         unsigned int prim_offset;
  7.     };
  8.  
  9.     union
  10.     {
  11.         unsigned int flags;
  12.         unsigned int prim_count;
  13.         unsigned int above_child;
  14.     };
  15. };
  16.  
  17. #define SPATIAL_STACK_SIZE 32
  18. struct KDStackNode
  19. {
  20.     unsigned int node;
  21.     float near, far;
  22.     float pad;
  23. };
  24.  
  25. __kernel void TraceSpatial(__global float4* triangles,
  26.     __global float4* rays,
  27.     __global float4* results,
  28.     __global struct KDNode* nodes,
  29.     __global unsigned int* indices,
  30.     float4 boundsMin,
  31.     float4 boundsMax,
  32.     int trianglesCount,
  33.     int raysCount,
  34.     int2 dimensions)
  35. {
  36.     int i = get_global_id(0);
  37.     int j = get_global_id(1);
  38.     if (i >= dimensions.x || j >= dimensions.y)
  39.     {
  40.         return;
  41.     }
  42.  
  43.     int k = i + j * dimensions.x;
  44.  
  45.     float4 o = rays[k * 4 + 0];
  46.     float4 d = rays[k * 4 + 1];
  47.     float4 inv = native_recip(d);
  48.    
  49.     struct KDStackNode stack[SPATIAL_STACK_SIZE];
  50.     unsigned int stack_ptr = 0;
  51.  
  52.     {
  53.         float4 v1 = (boundsMin - o) * inv;
  54.         float4 v2 = (boundsMax - o) * inv;
  55.         float4 near = min(v1, v2);
  56.         float4 far = max(v1, v2);
  57.         float enter = max(near.x, max(near.y, near.z));
  58.         float exit = min(far.x, min(far.y, far.z));
  59.  
  60.         if (exit > 0.0f && enter < exit)
  61.         {
  62.             stack[stack_ptr].node = 0;
  63.             stack[stack_ptr].near = enter;
  64.             stack[stack_ptr].far = exit;
  65.             stack_ptr++;
  66.  
  67.         }
  68.     }
  69.  
  70.     int id = -1;
  71.     float bu = 0.0f, bv = 0.0f;
  72.     float dist = d.w;
  73.  
  74. #ifdef RENDER_STATISTICS
  75.     int visited = 0;
  76.     int interiors = 0;
  77.     int leaves = 0;
  78. #elif defined MEMORY_STATISTICS
  79.     int globalop = 0;
  80.     int privateop = 0;
  81. #endif
  82.  
  83.     unsigned int node;
  84.  
  85.     while (stack_ptr != 0)
  86.     {
  87.         stack_ptr--;
  88.         node = stack[stack_ptr].node;
  89.         float near = stack[stack_ptr].near;
  90.  
  91.         float far = stack[stack_ptr].far;
  92.  
  93.         uint axis = (nodes[node].flags & 3);
  94.         uint above_child = (nodes[node].above_child >> 2);
  95.         float split = nodes[node].split;
  96.  
  97.  
  98. #ifdef MEMORY_STATISTICS
  99.         globalop += 3;
  100.         privateop += 3;
  101. #endif
  102.  
  103.  
  104.         while (axis != 3)
  105.         {
  106. #ifdef RENDER_STATISTICS
  107.  
  108.             visited++;
  109.             interiors++;
  110. #endif
  111.  
  112.             float hitpos;
  113.  
  114.             int below_first;
  115.             unsigned int first, second;
  116.  
  117.             float orig_tmp;
  118.             float idir_tmp;
  119.  
  120.  
  121.             switch (axis)
  122.             {
  123.             case 0:
  124.                 orig_tmp = o.x;
  125.  
  126.                 idir_tmp = inv.x;
  127.                 break;
  128.  
  129.             case 1:
  130.                 orig_tmp = o.y;
  131.  
  132.                 idir_tmp = inv.y;
  133.                 break;
  134.  
  135.             case 2:
  136.  
  137.  
  138.                 orig_tmp = o.z;
  139.                 idir_tmp = inv.z;
  140.                 break;
  141.             }
  142.  
  143.  
  144.             hitpos = (split - orig_tmp) * idir_tmp;
  145.             below_first = (orig_tmp < split) || (orig_tmp == split && idir_tmp >= 0.0f);
  146.  
  147.             if (below_first)
  148.             {
  149.  
  150.                 first = node + 1;
  151.                 second = above_child;
  152.             }
  153.             else
  154.             {
  155.  
  156.                 first = above_child;
  157.                 second = node + 1;
  158.             }
  159.  
  160.             if (hitpos > far || hitpos < 0.0f)
  161.  
  162.             {
  163.                 node = first;
  164.             }
  165.             else if (hitpos < near)
  166.             {
  167.  
  168.                 node = second;
  169.             }
  170.             else
  171.             {
  172.                 stack[stack_ptr].node = second;
  173.  
  174.                 stack[stack_ptr].near = hitpos;
  175.                 stack[stack_ptr].far = far;
  176.                 stack_ptr++;
  177. #ifdef MEMORY_STATISTICS
  178.                 privateop += 3;
  179. #endif
  180.  
  181.                 node = first;
  182.                 far = hitpos;
  183.             }
  184.  
  185.  
  186.             axis = (nodes[node].flags & 3);
  187.             above_child = (nodes[node].above_child >> 2);
  188.             split = nodes[node].split;
  189. #ifdef MEMORY_STATISTICS
  190.             globalop += 3;
  191. #endif
  192.         }
  193.  
  194.         unsigned int prim_offset = nodes[node].prim_offset;
  195.  
  196. #ifdef MEMORY_STATISTICS
  197.         globalop += 1;
  198. #endif
  199.         unsigned int prims_num = above_child;
  200.  
  201.  
  202. #ifdef RENDER_STATISTICS
  203.         visited++;
  204.         leaves += prims_num;
  205. #endif
  206.  
  207.  
  208.         if (prims_num > 0)
  209.         {
  210.             __global unsigned int *prims_ids = &indices[prim_offset];
  211.  
  212.             for (unsigned int n = 0; n < prims_num; n++)
  213.             {
  214.                 // Don't trash cache by reading index through it
  215.                 int tri_idx = prims_ids[n] * 3;
  216.                 float4 r = triangles[tri_idx + 0];
  217.                 float4 p = triangles[tri_idx + 1];
  218.                 float4 q = triangles[tri_idx + 2];
  219. #ifdef MEMORY_STATISTICS
  220.                 globalop += 4;
  221. #endif
  222.  
  223.                 float o_z = r.w - o.x * r.x - o.y * r.y - o.z * r.z;
  224.                 float i_z = 1.0f / (d.x * r.x + d.y * r.y + d.z * r.z);
  225.                 float t = o_z * i_z;
  226.  
  227.                 if (t > o.w && t < dist)
  228.  
  229.                 {
  230.                     float o_x = p.w + o.x * p.x + o.y * p.y + o.z * p.z;
  231.                     float d_x = d.x * p.x + d.y * p.y + d.z * p.z;
  232.                     float u = o_x + t * d_x;
  233.  
  234.  
  235.                     if (u >= 0.0f && u <= 1.0f)
  236.                     {
  237.                         float o_y = q.w + o.x * q.x + o.y * q.y + o.z * q.z;
  238.                         float d_y = d.x * q.x + d.y * q.y + d.z * q.z;
  239.                         float v = o_y + t * d_y;
  240.  
  241.  
  242.                         if (v >= 0.0f && u + v <= 1.0f)
  243.                         {
  244.                             dist = t;
  245.                             bu = u;
  246.  
  247.                             bv = v;
  248.                             id = tri_idx;
  249.                         }
  250.                     }
  251.                 }
  252.  
  253.             }
  254.  
  255.             if (dist < far)
  256.             {
  257.  
  258.                 break;
  259.             }
  260.         }
  261.     }
  262.  
  263.  
  264. #ifdef RENDER_STATISTICS
  265.     results[k] = (float4)((float)visited * 0.01f, (float)interiors * 0.01f, (float)leaves * 0.01f, 1.0f);
  266. #elif defined MEMORY_STATISTICS
  267.     results[k] = (float4)((float)globalop * 0.004f, (float)privateop * 0.004f, 0.0f, 1.0f);
  268. #else
  269.     results[k] = (float4)(bu, bv, dist, as_float(id));
  270. #endif
  271. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement