clray
changeset 35:7d77ded5f890
stopped using a heap to flatten the kdtree. added explicit left/right indices
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 26 Aug 2010 20:24:07 +0100 |
parents | 931d13b72f83 |
children | 4dec8853bf75 |
files | rt.cl src/rt.cc src/scene.cc src/scene.h |
diffstat | 4 files changed, 100 insertions(+), 53 deletions(-) [+] |
line diff
1.1 --- a/rt.cl Tue Aug 24 05:47:04 2010 +0100 1.2 +++ b/rt.cl Thu Aug 26 20:24:07 2010 +0100 1.3 @@ -62,7 +62,8 @@ 1.4 struct AABBox aabb; 1.5 int face_idx[32]; 1.6 int num_faces; 1.7 - int padding[3]; 1.8 + int left, right; 1.9 + int padding; 1.10 }; 1.11 1.12 #define MIN_ENERGY 0.001 1.13 @@ -117,9 +118,9 @@ 1.14 ray.origin = sp.pos; 1.15 ray.dir = reflect(-ray.dir, sp.norm); 1.16 1.17 - energy *= sp.mat.ks * sp.mat.kr; 1.18 + energy *= refl_col; 1.19 } else { 1.20 - iter = INT_MAX - 1; // to break out of the loop 1.21 + break; 1.22 } 1.23 } 1.24 1.25 @@ -171,7 +172,7 @@ 1.26 1.27 int idxstack[STACK_SIZE]; 1.28 int top = 0; // points after the topmost element of the stack 1.29 - idxstack[top++] = 1; // root at tree[1] (heap) 1.30 + idxstack[top++] = 0; // root at tree[0] 1.31 1.32 while(top > 0) { 1.33 int idx = idxstack[--top]; // remove this index from the stack and process it 1.34 @@ -186,7 +187,7 @@ 1.35 }*/ 1.36 1.37 if(intersect_aabb(ray, node->aabb)) { 1.38 - if(node->num_faces >= 0) { 1.39 + if(node->left == -1) { 1.40 // leaf node... check each face in turn and update the nearest intersection as needed 1.41 for(int i=0; i<node->num_faces; i++) { 1.42 struct SurfPoint spt; 1.43 @@ -199,10 +200,10 @@ 1.44 } else { 1.45 // internal node... recurse to the children 1.46 /*if(get_global_id(0) == 0) { 1.47 - printf("pushing %d's children %d and %d\n", idx, idx * 2, idx * 2 + 1); 1.48 + printf("pushing %d's children %d and %d\n", idx, node->left, node->right); 1.49 }*/ 1.50 - idxstack[top++] = idx * 2; 1.51 - idxstack[top++] = idx * 2 + 1; 1.52 + idxstack[top++] = node->left; 1.53 + idxstack[top++] = node->right; 1.54 } 1.55 } 1.56 }
2.1 --- a/src/rt.cc Tue Aug 24 05:47:04 2010 +0100 2.2 +++ b/src/rt.cc Thu Aug 26 20:24:07 2010 +0100 2.3 @@ -102,7 +102,7 @@ 2.4 prog->set_arg_buffer(KARG_PRIM_RAYS, ARG_RD, xsz * ysz * sizeof *prim_rays, prim_rays); 2.5 prog->set_arg_buffer(KARG_XFORM, ARG_RD, 16 * sizeof(float)); 2.6 prog->set_arg_buffer(KARG_INVTRANS_XFORM, ARG_RD, 16 * sizeof(float)); 2.7 - prog->set_arg_buffer(KARG_KDTREE, ARG_RD, scn->get_kdtree_buffer_size(), kdbuf); 2.8 + prog->set_arg_buffer(KARG_KDTREE, ARG_RD, scn->get_num_kdnodes() * sizeof *kdbuf, kdbuf); 2.9 2.10 if(prog->get_num_args() < NUM_KERNEL_ARGS) { 2.11 return false;
3.1 --- a/src/scene.cc Tue Aug 24 05:47:04 2010 +0100 3.2 +++ b/src/scene.cc Thu Aug 26 20:24:07 2010 +0100 3.3 @@ -1,15 +1,18 @@ 3.4 +#include <stdlib.h> 3.5 #include <math.h> 3.6 #include <float.h> 3.7 #include <assert.h> 3.8 +#include <map> 3.9 #include "scene.h" 3.10 #include "ogl.h" 3.11 3.12 3.13 +static void flatten_kdtree(const KDNode *node, KDNodeGPU *kdbuf, int *count, std::map<const KDNode*, int> *flatmap); 3.14 +static void fix_child_links(const KDNode *node, KDNodeGPU *kdbuf, const std::map<const KDNode*, int> &flatmap); 3.15 static void draw_kdtree(const KDNode *node, int level = 0); 3.16 static bool build_kdtree(KDNode *kd, const Face *faces, int level = 0); 3.17 static float eval_cost(const Face *faces, const int *face_idx, int num_faces, const AABBox &aabb, int axis); 3.18 static void free_kdtree(KDNode *node); 3.19 -static void kdtree_gpu_flatten(KDNodeGPU *kdbuf, int idx, const KDNode *node); 3.20 static void print_item_counts(const KDNode *node, int level); 3.21 3.22 3.23 @@ -123,6 +126,11 @@ 3.24 return (int)matlib.size(); 3.25 } 3.26 3.27 +int Scene::get_num_kdnodes() const 3.28 +{ 3.29 + return kdtree_nodes(kdtree); 3.30 +} 3.31 + 3.32 Material *Scene::get_materials() 3.33 { 3.34 if(matlib.empty()) { 3.35 @@ -159,6 +167,27 @@ 3.36 return facebuf; 3.37 } 3.38 3.39 +static int find_node_index(const KDNode *node, const std::map<const KDNode*, int> &flatmap); 3.40 + 3.41 +static bool validate_flat_tree(const KDNode *node, const KDNodeGPU *kdbuf, int count, const std::map<const KDNode*, int> &flatmap) 3.42 +{ 3.43 + if(!node) return true; 3.44 + 3.45 + int idx = find_node_index(node, flatmap); 3.46 + int left_idx = find_node_index(node->left, flatmap); 3.47 + int right_idx = find_node_index(node->right, flatmap); 3.48 + 3.49 + if(kdbuf[idx].left != left_idx) { 3.50 + fprintf(stderr, "%d's left should be %d. it's: %d\n", idx, left_idx, kdbuf[idx].left); 3.51 + return false; 3.52 + } 3.53 + if(kdbuf[idx].right != right_idx) { 3.54 + fprintf(stderr, "%d's right should be %d. it's: %d\n", idx, right_idx, kdbuf[idx].right); 3.55 + return false; 3.56 + } 3.57 + return validate_flat_tree(node->left, kdbuf, count, flatmap) && validate_flat_tree(node->right, kdbuf, count, flatmap); 3.58 +} 3.59 + 3.60 const KDNodeGPU *Scene::get_kdtree_buffer() const 3.61 { 3.62 if(kdbuf) { 3.63 @@ -169,29 +198,72 @@ 3.64 ((Scene*)this)->build_kdtree(); 3.65 } 3.66 3.67 - int max_nodes = (int)pow(2, kdtree_depth(kdtree)) - 1; 3.68 - printf("allocating storage for the complete tree (%d)\n", max_nodes); 3.69 + /* we'll associate kdnodes with flattened array indices through this map as 3.70 + * we add them so that the second child-index pass, will be able to find 3.71 + * the children indices of each node. 3.72 + */ 3.73 + std::map<const KDNode*, int> flatmap; 3.74 + flatmap[0] = -1; 3.75 3.76 - kdbuf = new KDNodeGPU[max_nodes + 1]; 3.77 - kdtree_gpu_flatten(kdbuf, 1, kdtree); 3.78 + int num_nodes = get_num_kdnodes(); 3.79 + kdbuf = new KDNodeGPU[num_nodes]; 3.80 + 3.81 + int count = 0; 3.82 + 3.83 + // first arrange the kdnodes into an array (flatten) 3.84 + flatten_kdtree(kdtree, kdbuf, &count, &flatmap); 3.85 + 3.86 + // then fix all the left/right links to point to the correct nodes 3.87 + fix_child_links(kdtree, kdbuf, flatmap); 3.88 + 3.89 + assert(validate_flat_tree(kdtree, kdbuf, count, flatmap)); 3.90 + 3.91 return kdbuf; 3.92 } 3.93 3.94 -static int ipow(int x, int n) 3.95 +static void flatten_kdtree(const KDNode *node, KDNodeGPU *kdbuf, int *count, std::map<const KDNode*, int> *flatmap) 3.96 { 3.97 - assert(n >= 0); 3.98 + int idx = (*count)++; 3.99 3.100 - int res = 1; 3.101 - for(int i=0; i<n; i++) { 3.102 - res *= x; 3.103 + // copy the node 3.104 + kdbuf[idx].aabb = node->aabb; 3.105 + for(size_t i=0; i<node->face_idx.size(); i++) { 3.106 + kdbuf[idx].face_idx[i] = node->face_idx[i]; 3.107 } 3.108 - return res; 3.109 + kdbuf[idx].num_faces = node->face_idx.size(); 3.110 + 3.111 + // update the node* -> array-position mapping 3.112 + (*flatmap)[node] = idx; 3.113 + 3.114 + // recurse to the left/right (if we're not in a leaf node) 3.115 + if(node->left) { 3.116 + assert(node->right); 3.117 + 3.118 + flatten_kdtree(node->left, kdbuf, count, flatmap); 3.119 + flatten_kdtree(node->right, kdbuf, count, flatmap); 3.120 + } 3.121 } 3.122 3.123 -int Scene::get_kdtree_buffer_size() const 3.124 +static int find_node_index(const KDNode *node, const std::map<const KDNode*, int> &flatmap) 3.125 { 3.126 - // 2**depth - 1 nodes for the complete tree + 1 for the unused heap item 0. 3.127 - return ipow(2, kdtree_depth(kdtree)) * sizeof(KDNodeGPU); 3.128 + std::map<const KDNode*, int>::const_iterator it = flatmap.find(node); 3.129 + assert(it != flatmap.end()); 3.130 + return it->second; 3.131 +} 3.132 + 3.133 +static void fix_child_links(const KDNode *node, KDNodeGPU *kdbuf, const std::map<const KDNode*, int> &flatmap) 3.134 +{ 3.135 + if(!node) return; 3.136 + 3.137 + int idx = find_node_index(node, flatmap); 3.138 + 3.139 + kdbuf[idx].left = find_node_index(node->left, flatmap); 3.140 + if(!node->left && kdbuf[idx].left != -1) abort(); 3.141 + kdbuf[idx].right = find_node_index(node->right, flatmap); 3.142 + if(!node->right && kdbuf[idx].right != -1) abort(); 3.143 + 3.144 + fix_child_links(node->left, kdbuf, flatmap); 3.145 + fix_child_links(node->right, kdbuf, flatmap); 3.146 } 3.147 3.148 void Scene::draw_kdtree() const 3.149 @@ -442,33 +514,6 @@ 3.150 return kdtree_nodes(node->left) + kdtree_nodes(node->right) + 1; 3.151 } 3.152 3.153 -#define MAX_FACES (sizeof dest->face_idx / sizeof *dest->face_idx) 3.154 -static void kdtree_gpu_flatten(KDNodeGPU *kdbuf, int idx, const KDNode *node) 3.155 -{ 3.156 - KDNodeGPU *dest = kdbuf + idx; 3.157 - 3.158 - dest->aabb = node->aabb; 3.159 - dest->num_faces = 0; 3.160 - 3.161 - for(size_t i=0; i<node->face_idx.size(); i++) { 3.162 - if(dest->num_faces >= (int)MAX_FACES) { 3.163 - fprintf(stderr, "kdtree_gpu_flatten WARNING: more than %d faces in node, skipping!\n", (int)MAX_FACES); 3.164 - break; 3.165 - } 3.166 - dest->face_idx[dest->num_faces++] = node->face_idx[i]; 3.167 - } 3.168 - 3.169 - if(node->left) { 3.170 - assert(node->right); 3.171 - assert(!dest->num_faces); 3.172 - 3.173 - dest->num_faces = -1; 3.174 - 3.175 - kdtree_gpu_flatten(kdbuf, idx * 2, node->left); 3.176 - kdtree_gpu_flatten(kdbuf, idx * 2 + 1, node->right); 3.177 - } 3.178 -} 3.179 - 3.180 static void print_item_counts(const KDNode *node, int level) 3.181 { 3.182 if(!node) return;
4.1 --- a/src/scene.h Tue Aug 24 05:47:04 2010 +0100 4.2 +++ b/src/scene.h Thu Aug 26 20:24:07 2010 +0100 4.3 @@ -54,7 +54,8 @@ 4.4 AABBox aabb; 4.5 int face_idx[32]; 4.6 int num_faces; 4.7 - int padding[3]; 4.8 + int left, right; 4.9 + int padding; 4.10 }; 4.11 4.12 4.13 @@ -75,8 +76,9 @@ 4.14 4.15 bool add_mesh(Mesh *m); 4.16 int get_num_meshes() const; 4.17 + int get_num_faces() const; 4.18 int get_num_materials() const; 4.19 - int get_num_faces() const; 4.20 + int get_num_kdnodes() const; 4.21 4.22 Material *get_materials(); 4.23 const Material *get_materials() const; 4.24 @@ -86,7 +88,6 @@ 4.25 4.26 const Face *get_face_buffer() const; 4.27 const KDNodeGPU *get_kdtree_buffer() const; 4.28 - int get_kdtree_buffer_size() const; 4.29 4.30 void draw_kdtree() const; 4.31 bool build_kdtree();