Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/makesdna/DNA_scene_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_scene.c26
-rw-r--r--source/blender/render/extern/include/RE_raytrace.h2
-rw-r--r--source/blender/render/intern/raytrace/bvh.h8
-rw-r--r--source/blender/render/intern/raytrace/qbvh.h0
-rw-r--r--source/blender/render/intern/raytrace/rayobject_bvh.cpp1
-rw-r--r--source/blender/render/intern/raytrace/rayobject_qbvh.cpp57
-rw-r--r--source/blender/render/intern/raytrace/rayobject_rtbuild.cpp28
-rw-r--r--source/blender/render/intern/raytrace/rayobject_svbvh.cpp42
-rw-r--r--source/blender/render/intern/raytrace/rayobject_vbvh.cpp2
-rw-r--r--source/blender/render/intern/raytrace/reorganize.h235
-rw-r--r--source/blender/render/intern/raytrace/svbvh.h13
-rw-r--r--source/blender/render/intern/raytrace/vbvh.h43
-rw-r--r--source/blender/render/intern/source/rayobject_raycounter.c9
-rw-r--r--source/blender/render/intern/source/rayshade.c138
15 files changed, 465 insertions, 155 deletions
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 6efd47d9348..82658be24bf 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -769,15 +769,13 @@ typedef struct Scene {
#define R_YAFRAY 1
/* raytrace structure */
-#define R_RAYSTRUCTURE_HIER_BVH_BVH 0
-#define R_RAYSTRUCTURE_HIER_BVH_OCTREE 1
-#define R_RAYSTRUCTURE_SINGLE_OCTREE 2
-#define R_RAYSTRUCTURE_SINGLE_BVH 3
-
-/* raytrace tree type */
-#define R_RAYTRACE_TREE_BVH 0
-#define R_RAYTRACE_TREE_BLIBVH 1
-#define R_RAYTRACE_TREE_BIH 2
+#define R_RAYSTRUCTURE_AUTO 0
+#define R_RAYSTRUCTURE_OCTREE 1
+#define R_RAYSTRUCTURE_BLIBVH 2
+#define R_RAYSTRUCTURE_VBVH 3
+#define R_RAYSTRUCTURE_SIMD_SVBVH 4 /* needs SIMD */
+#define R_RAYSTRUCTURE_SIMD_QBVH 5 /* needs SIMD */
+#define R_RAYSTRUCTURE_BIH 6
/* scemode (int now) */
#define R_DOSEQ 0x0001
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 7baf8c8fd93..db832f1d31c 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1032,18 +1032,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem raytrace_structure_items[] = {
- {R_RAYSTRUCTURE_HIER_BVH_BVH, "{R_RAYSTRUCTURE_HIER_BVH_BVH", 0, "BVH of BVH's", "Create a BVH of objects (each object has it own BVH)"},
- {R_RAYSTRUCTURE_HIER_BVH_OCTREE, "{R_RAYSTRUCTURE_HIER_BVH_OCTREE", 0, "BVH of octree", "Create a BVH of objects (each object has it own octree)"},
- {R_RAYSTRUCTURE_SINGLE_BVH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "Single BVH", "BVH of all primitives (no instance support)"},
- {R_RAYSTRUCTURE_SINGLE_OCTREE, "{R_RAYSTRUCTURE_SINGLE_OCTREE", 0, "Octree", "Octree of all primitives (no instance support)"},
- {0, NULL, 0, NULL, NULL}};
+ {R_RAYSTRUCTURE_AUTO, "{R_RAYSTRUCTURE_AUTO", 0, "auto", ""},
+ {R_RAYSTRUCTURE_OCTREE, "R_RAYSTRUCTURE_OCTREE", 0, "octree", "Use old octree structure (no support for instances)"},
+ {R_RAYSTRUCTURE_BLIBVH, "R_RAYSTRUCTURE_BLIBVH", 0, "blibvh", "Use BLI_kdopbvh.c"},
+ {R_RAYSTRUCTURE_VBVH, "R_RAYSTRUCTURE_VBVH", 0, "vBVH", ""},
+ {R_RAYSTRUCTURE_SIMD_SVBVH, "R_RAYSTRUCTURE_SIMD_SVBVH", 0, "SIMD SVBVH", "Requires SIMD"},
+ {R_RAYSTRUCTURE_SIMD_QBVH, "R_RAYSTRUCTURE_SIMD_QBVH", 0, "SIMD QBVH", "Requires SIMD"},
+ {R_RAYSTRUCTURE_BIH, "R_RAYSTRUCTURE_BIH", 0, "BIH", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
- static EnumPropertyItem raytrace_tree_type_items[] = {
- {R_RAYTRACE_TREE_BVH, "{R_RAYTRACE_TREE_BVH", 0, "BVH", "rayobject_bvh.c"},
- {R_RAYTRACE_TREE_BLIBVH, "{R_RAYTRACE_TREE_BLIBVH", 0, "BLIbvh", "rayobject_blibvh.c"},
- {R_RAYTRACE_TREE_BIH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "BIH", "rayobject_bih.c"},
- {0, NULL, 0, NULL, NULL}};
-
static EnumPropertyItem fixed_oversample_items[] = {
{5, "OVERSAMPLE_5", 0, "5", ""},
{8, "OVERSAMPLE_8", 0, "8", ""},
@@ -1462,12 +1460,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Raytrace Acceleration Structure", "Type of raytrace accelerator structure.");
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
- prop= RNA_def_property(srna, "raytrace_tree_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "raytrace_tree_type");
- RNA_def_property_enum_items(prop, raytrace_tree_type_items);
- RNA_def_property_ui_text(prop, "Raytrace tree type", "Type of raytrace accelerator structure.");
- RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
-
prop= RNA_def_property(srna, "antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA);
RNA_def_property_ui_text(prop, "Anti-Aliasing", "Render and combine multiple samples per pixel to prevent jagged edges.");
diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h
index 01b64c15058..c775a7d18ef 100644
--- a/source/blender/render/extern/include/RE_raytrace.h
+++ b/source/blender/render/extern/include/RE_raytrace.h
@@ -53,7 +53,7 @@ struct RayCounter
{
unsigned long long test, hit;
- } faces, bb, raycast, raytrace_hint, rayshadow_last_hit;
+ } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit;
};
/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */
diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h
index 21234a40673..7d3479e5331 100644
--- a/source/blender/render/intern/raytrace/bvh.h
+++ b/source/blender/render/intern/raytrace/bvh.h
@@ -241,17 +241,13 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec)
t_node[i] = t->child;
}
*/
- RE_RC_COUNT(isec->raycounter->bb.test);
- RE_RC_COUNT(isec->raycounter->bb.test);
- RE_RC_COUNT(isec->raycounter->bb.test);
- RE_RC_COUNT(isec->raycounter->bb.test);
-
+ RE_RC_COUNT(isec->raycounter->simd_bb.test);
int res = test_bb_group4( t_bb, isec );
for(int i=0; i<4; i++)
if(res & (1<<i))
{
- RE_RC_COUNT(isec->raycounter->bb.hit);
+ RE_RC_COUNT(isec->raycounter->simd_bb.hit);
if(!is_leaf(t_node[i]))
{
for(Node *t=t_node[i]; t; t=t->sibling)
diff --git a/source/blender/render/intern/raytrace/qbvh.h b/source/blender/render/intern/raytrace/qbvh.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/source/blender/render/intern/raytrace/qbvh.h
+++ /dev/null
diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp
index bf54f889ebf..a7e96f6d3fc 100644
--- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp
@@ -65,7 +65,6 @@ struct BVHTree
RTBuilder *builder;
};
-
/*
* Push nodes (used on dfs)
*/
diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
index e3a15b5d7f3..53579d2915f 100644
--- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp
@@ -1,6 +1,33 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
#include "vbvh.h"
#include "svbvh.h"
-#include "qbvh.h"
#include "reorganize.h"
#define DFS_STACK_SIZE 256
@@ -17,6 +44,17 @@ struct QBVHTree
};
+/*
+ * Cost to test N childs
+ */
+struct PackCost
+{
+ float operator()(int n)
+ {
+ return (n / 4) + ((n % 4) > 2 ? 1 : n%4);
+ }
+};
+
template<>
void bvh_done<QBVHTree>(QBVHTree *obj)
{
@@ -31,9 +69,20 @@ void bvh_done<QBVHTree>(QBVHTree *obj)
BLI_memarena_use_align(arena2, 16);
//Build and optimize the tree
- VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder);
- pushup_simd<VBVHNode,4>(root);
- obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root);
+
+ if(0)
+ {
+ VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1).transform(obj->builder);
+ pushup_simd<VBVHNode,4>(root);
+ obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root);
+ }
+ else
+ {
+ //Finds the optimal packing of this tree using a given cost model
+ OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena1).transform(obj->builder);
+ VBVH_optimalPackSIMD<OVBVHNode,PackCost>(PackCost()).transform(root);
+ obj->root = Reorganize_SVBVH<OVBVHNode>(arena2).transform(root);
+ }
//Cleanup
BLI_memarena_free(arena1);
diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
index 238929e1dbb..430045b56b6 100644
--- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
@@ -1,3 +1,31 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
#include <assert.h>
#include <math.h>
#include <stdlib.h>
diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
index df033901526..1bcffddd0ac 100644
--- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp
@@ -1,3 +1,31 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
#include "vbvh.h"
#include "svbvh.h"
#include "reorganize.h"
@@ -25,9 +53,12 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
BLI_memarena_use_malloc(arena1);
- //Build and optimize the tree
- VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder);
+ MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+ BLI_memarena_use_malloc(arena2);
+ BLI_memarena_use_align(arena2, 16);
+ //Build and optimize the tree
+ VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1).transform(obj->builder);
reorganize(root);
remove_useless(root, &root);
bvh_refit(root);
@@ -35,12 +66,11 @@ void bvh_done<SVBVHTree>(SVBVHTree *obj)
pushup(root);
pushdown(root);
pushup_simd<VBVHNode,4>(root);
-
- MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
- BLI_memarena_use_malloc(arena2);
- BLI_memarena_use_align(arena2, 16);
+
obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root);
+
+ //Free data
BLI_memarena_free(arena1);
obj->node_arena = arena2;
diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
index f81ca1e5d1b..4e51de0da07 100644
--- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
@@ -70,7 +70,7 @@ void bvh_done<VBVHTree>(VBVHTree *obj)
//Build and optimize the tree
- VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder);
+ VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1).transform(obj->builder);
reorganize(root);
remove_useless(root, &root);
diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h
index 712221fb739..f0335b769d5 100644
--- a/source/blender/render/intern/raytrace/reorganize.h
+++ b/source/blender/render/intern/raytrace/reorganize.h
@@ -26,7 +26,10 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+#include <stdio.h>
+#include <math.h>
#include <algorithm>
+#include <vector>
#include <queue>
extern int tot_pushup;
@@ -279,3 +282,235 @@ float bvh_refit(Node *node)
total += old_area - bb_area(node->bb, node->bb+3);
return total;
}
+
+
+/*
+ * this finds the best way to packing a tree acording to a given test cost function
+ * with the purpose to reduce the expected cost (eg.: number of BB tests).
+ */
+#include <vector>
+#include <cmath>
+#define MAX_CUT_SIZE 16
+#define MAX_OPTIMIZE_CHILDS MAX_CUT_SIZE
+
+struct OVBVHNode
+{
+ float bb[6];
+
+ OVBVHNode *child;
+ OVBVHNode *sibling;
+
+ /*
+ * Returns min cost to represent the subtree starting at the given node,
+ * allowing it to have a given cutsize
+ */
+ float cut_cost[MAX_CUT_SIZE];
+ float get_cost(int cutsize)
+ {
+ return cut_cost[cutsize-1];
+ }
+
+ /*
+ * This saves the cut size of this child, when parent is reaching
+ * its minimum cut with the given cut size
+ */
+ int cut_size[MAX_CUT_SIZE];
+ int get_cut_size(int parent_cut_size)
+ {
+ return cut_size[parent_cut_size-1];
+ }
+
+ /*
+ * Reorganize the node based on calculated cut costs
+ */
+ int best_cutsize;
+ void set_cut(int cutsize, OVBVHNode ***cut)
+ {
+ if(cutsize == 1)
+ {
+ **cut = this;
+ *cut = &(**cut)->sibling;
+ }
+ else
+ {
+ if(cutsize > MAX_CUT_SIZE)
+ {
+ for(OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling)
+ {
+ child->set_cut( 1, cut );
+ cutsize--;
+ }
+ assert(cutsize == 0);
+ }
+ else
+ for(OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling)
+ child->set_cut( child->get_cut_size( cutsize ), cut );
+ }
+ }
+
+ void optimize()
+ {
+ if(RE_rayobject_isAligned(this->child))
+ {
+ //Calc new childs
+ {
+ OVBVHNode **cut = &(this->child);
+ set_cut( best_cutsize, &cut );
+ *cut = NULL;
+ }
+
+ //Optimize new childs
+ for(OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling)
+ child->optimize();
+ }
+ }
+};
+
+/*
+ * Calculates an optimal SIMD packing
+ *
+ */
+template<class Node, class TestCost>
+struct VBVH_optimalPackSIMD
+{
+ TestCost testcost;
+
+ VBVH_optimalPackSIMD(TestCost testcost)
+ {
+ this->testcost = testcost;
+ }
+
+ /*
+ * calc best cut on a node
+ */
+ struct calc_best
+ {
+ Node *child[MAX_OPTIMIZE_CHILDS];
+ float child_hit_prob[MAX_OPTIMIZE_CHILDS];
+
+ calc_best(Node *node)
+ {
+ int nchilds = 0;
+ //Fetch childs and needed data
+ {
+ float parent_area = bb_area(node->bb, node->bb+3);
+ for(Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling)
+ {
+ this->child[nchilds] = child;
+ this->child_hit_prob[nchilds] = bb_area(child->bb, child->bb+3) / parent_area;
+ nchilds++;
+ }
+
+ assert(nchilds >= 2 && nchilds <= MAX_OPTIMIZE_CHILDS);
+ }
+
+
+ //Build DP table to find minimum cost to represent this node with a given cutsize
+ int bt [MAX_OPTIMIZE_CHILDS+1][MAX_CUT_SIZE+1]; //backtrace table
+ float cost[MAX_OPTIMIZE_CHILDS+1][MAX_CUT_SIZE+1]; //cost table (can be reduced to float[2][MAX_CUT_COST])
+
+ for(int i=0; i<=nchilds; i++)
+ for(int j=0; j<=MAX_CUT_SIZE; j++)
+ cost[i][j] = INFINITY;
+
+ cost[0][0] = 0;
+
+ for(int i=1; i<=nchilds; i++)
+ for(int size=i-1; size/*+(nchilds-i)*/<=MAX_CUT_SIZE; size++)
+ for(int cut=1; cut+size/*+(nchilds-i)*/<=MAX_CUT_SIZE; cut++)
+ {
+ float new_cost = cost[i-1][size] + child_hit_prob[i-1]*child[i-1]->get_cost(cut);
+ if(new_cost < cost[i][size+cut])
+ {
+ cost[i][size+cut] = new_cost;
+ bt[i][size+cut] = cut;
+ }
+ }
+
+ //Save the ways to archieve the minimum cost with a given cutsize
+ for(int i = nchilds; i <= MAX_CUT_SIZE; i++)
+ {
+ node->cut_cost[i-1] = cost[nchilds][i];
+ if(cost[nchilds][i] < INFINITY)
+ {
+ int current_size = i;
+ for(int j=nchilds; j>0; j--)
+ {
+ child[j-1]->cut_size[i-1] = bt[j][current_size];
+ current_size -= bt[j][current_size];
+ }
+ }
+ }
+ }
+ };
+
+ void calc_costs(Node *node)
+ {
+
+ if( RE_rayobject_isAligned(node->child) )
+ {
+ int nchilds = 0;
+ for(Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling)
+ {
+ calc_costs(child);
+ nchilds++;
+ }
+
+ for(int i=0; i<MAX_CUT_SIZE; i++)
+ node->cut_cost[i] = INFINITY;
+
+ //We are not allowed to look on nodes with with so many childs
+ if(nchilds > MAX_CUT_SIZE)
+ {
+ float cost = 0;
+
+ float parent_area = bb_area(node->bb, node->bb+3);
+ for(Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling)
+ {
+ cost += ( bb_area(child->bb, child->bb+3) / parent_area ) * child->get_cost(1);
+ }
+
+ cost += testcost(nchilds);
+ node->cut_cost[0] = cost;
+ node->best_cutsize = nchilds;
+ }
+ else
+ {
+ calc_best calc(node);
+
+ //calc expected cost if we optimaly pack this node
+ for(int cutsize=nchilds; cutsize<=MAX_CUT_SIZE; cutsize++)
+ {
+ float m = node->get_cost(cutsize) + testcost(cutsize);
+ if(m < node->cut_cost[0])
+ {
+ node->cut_cost[0] = m;
+ node->best_cutsize = cutsize;
+ }
+ }
+ }
+ assert(node->cut_cost[0] != INFINITY);
+ }
+ else
+ {
+ node->cut_cost[0] = 1.0f;
+ for(int i=1; i<MAX_CUT_SIZE; i++)
+ node->cut_cost[i] = INFINITY;
+ }
+ }
+
+ Node *transform(Node *node)
+ {
+ if(RE_rayobject_isAligned(node->child))
+ {
+ static int num = 0;
+ bool first = false;
+ if(num == 0) { num++; first = true; }
+
+ calc_costs(node);
+ if(first) printf("expected cost = %f (%d)\n", node->cut_cost[0], node->best_cutsize );
+ node->optimize();
+ }
+ return node;
+ }
+};
diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h
index b243e91d381..840ccc24d1a 100644
--- a/source/blender/render/intern/raytrace/svbvh.h
+++ b/source/blender/render/intern/raytrace/svbvh.h
@@ -56,15 +56,12 @@ inline void bvh_node_push_childs<SVBVHNode>(SVBVHNode *node, Isect *isec, SVBVHN
while(i+4 <= node->nchilds)
{
int res = test_bb_group4( (__m128*) (node->child_bb+6*i), isec );
- RE_RC_COUNT(isec->raycounter->bb.test);
- RE_RC_COUNT(isec->raycounter->bb.test);
- RE_RC_COUNT(isec->raycounter->bb.test);
- RE_RC_COUNT(isec->raycounter->bb.test);
+ RE_RC_COUNT(isec->raycounter->simd_bb.test);
- if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->bb.hit); }
- if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->bb.hit); }
- if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->bb.hit); }
- if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->bb.hit); }
+ if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+ if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+ if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
+ if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); }
i += 4;
}
diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h
index 7c07bd9ded0..db1df43f665 100644
--- a/source/blender/render/intern/raytrace/vbvh.h
+++ b/source/blender/render/intern/raytrace/vbvh.h
@@ -1,3 +1,31 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
#include <assert.h>
#include <algorithm>
@@ -75,6 +103,7 @@ void append_sibling(Node *node, Node *sibling)
/*
* Builds a binary VBVH from a rtbuild
*/
+template<class Node>
struct BuildBinaryVBVH
{
MemArena *arena;
@@ -84,9 +113,9 @@ struct BuildBinaryVBVH
arena = a;
}
- VBVHNode *create_node()
+ Node *create_node()
{
- VBVHNode *node = (VBVHNode*)BLI_memarena_alloc( arena, sizeof(VBVHNode) );
+ Node *node = (Node*)BLI_memarena_alloc( arena, sizeof(Node) );
assert( RE_rayobject_isAligned(node) );
node->sibling = NULL;
@@ -100,26 +129,26 @@ struct BuildBinaryVBVH
return ::rtbuild_heuristic_object_split(builder, 2);
}
- VBVHNode *transform(RTBuilder *builder)
+ Node *transform(RTBuilder *builder)
{
int size = rtbuild_size(builder);
if(size == 1)
{
- VBVHNode *node = create_node();
+ Node *node = create_node();
INIT_MINMAX(node->bb, node->bb+3);
rtbuild_merge_bb(builder, node->bb, node->bb+3);
- node->child = (VBVHNode*) rtbuild_get_primitive( builder, 0 );
+ node->child = (Node*) rtbuild_get_primitive( builder, 0 );
return node;
}
else
{
- VBVHNode *node = create_node();
+ Node *node = create_node();
INIT_MINMAX(node->bb, node->bb+3);
rtbuild_merge_bb(builder, node->bb, node->bb+3);
- VBVHNode **child = &node->child;
+ Node **child = &node->child;
int nc = rtbuild_split(builder);
assert(nc == 2);
diff --git a/source/blender/render/intern/source/rayobject_raycounter.c b/source/blender/render/intern/source/rayobject_raycounter.c
index 83ba15602da..b47df607c10 100644
--- a/source/blender/render/intern/source/rayobject_raycounter.c
+++ b/source/blender/render/intern/source/rayobject_raycounter.c
@@ -39,6 +39,9 @@ void RE_RC_INFO(RayCounter *info)
printf("BB tests: %llu\n", info->bb.test );
printf("BB hits: %llu\n", info->bb.hit );
printf("\n");
+ printf("SIMD BB tests: %llu\n", info->simd_bb.test );
+ printf("SIMD BB hits: %llu\n", info->simd_bb.hit );
+ printf("\n");
printf("Primitives tests: %llu\n", info->faces.test );
printf("Primitives hits: %llu\n", info->faces.hit );
printf("------------------------------------\n");
@@ -51,6 +54,9 @@ void RE_RC_INFO(RayCounter *info)
printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) );
printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) );
printf("\n");
+ printf("SIMD tests per ray: %f\n", info->simd_bb.test / ((float)info->raycast.test) );
+ printf("SIMD hits per ray: %f\n", info->simd_bb.hit / ((float)info->raycast.test) );
+ printf("\n");
printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) );
printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) );
printf("------------------------------------\n");
@@ -64,6 +70,9 @@ void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp)
dest->bb.test += tmp->bb.test;
dest->bb.hit += tmp->bb.hit;
+ dest->simd_bb.test += tmp->simd_bb.test;
+ dest->simd_bb.hit += tmp->simd_bb.hit;
+
dest->raycast.test += tmp->raycast.test;
dest->raycast.hit += tmp->raycast.hit;
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 928083620e1..727d5826e49 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -69,21 +69,47 @@
/* only to be used here in this file, it's for speed */
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-
-RayObject * RE_rayobject_tree_create(int type, int size) __attribute__((noinline));
-
-RayObject * RE_rayobject_tree_create(int type, int size)
+RayObject * RE_rayobject_create(int type, int size)
{
-// if(type == R_RAYTRACE_TREE_BIH)
- return RE_rayobject_svbvh_create(size);
-
- if(type == R_RAYTRACE_TREE_BVH)
- return RE_rayobject_bvh_create(size);
- if(type == R_RAYTRACE_TREE_BIH)
- return RE_rayobject_bih_create(size);
- if(type == R_RAYTRACE_TREE_BLIBVH)
- return RE_rayobject_blibvh_create(size);
+ if(type == R_RAYSTRUCTURE_AUTO)
+ {
+ //TODO
+// if(detect_simd())
+// type = R_RAYSTRUCTURE_SIMD_SVBVH;
+// else
+// type = R_RAYSTRUCTURE_VBVH;
+ type = R_RAYSTRUCTURE_SIMD_QBVH;
+ }
+
+
+ if(type == R_RAYSTRUCTURE_OCTREE)
+ {
+ //TODO dynamic ocres
+ return RE_rayobject_octree_create(R.r.ocres, size);
+ }
+ if(type == R_RAYSTRUCTURE_BLIBVH)
+ {
+ return RE_rayobject_blibvh_create(size);
+ }
+ if(type == R_RAYSTRUCTURE_VBVH)
+ {
+ return RE_rayobject_vbvh_create(size);
+ }
+ if(type == R_RAYSTRUCTURE_SIMD_SVBVH)
+ {
+ return RE_rayobject_svbvh_create(size);
+ }
+ if(type == R_RAYSTRUCTURE_SIMD_QBVH)
+ {
+ return RE_rayobject_qbvh_create(size);
+ }
+ if(type == R_RAYSTRUCTURE_BIH)
+ {
+// return RE_rayobject_bih_create(size);
+ }
+
+ return NULL;
}
#ifdef RE_RAYCOUNTER
@@ -205,14 +231,8 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
}
assert( faces > 0 );
- //Create Ray cast accelaration structure
-
- //TODO dynamic ocres
- if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE)
- raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
- else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH)
- raytree = obr->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces );
-
+ //Create Ray cast accelaration structure
+ raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces );
face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces");
obr->rayobi = obi;
@@ -239,51 +259,6 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
return obi->obr->raytree;
}
-/*
- * create an hierarchic raytrace structure with all objects
- *
- * R_TRANSFORMED objects instances reuse the same tree by using the rayobject_instance
- */
-static void makeraytree_hier(Render *re)
-{
- //TODO
- // out-of-memory safeproof
- // break render
- // update render stats
-
- ObjectInstanceRen *obi;
- int num_objects = 0;
-
- re->i.infostr="Creating raytrace structure";
- re->stats_draw(re->sdh, &re->i);
-
- //Count number of objects
- for(obi=re->instancetable.first; obi; obi=obi->next)
- if(is_raytraceable(re, obi))
- num_objects++;
-
- //Create raytree
- re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, num_objects );
-
- for(obi=re->instancetable.first; obi; obi=obi->next)
- if(is_raytraceable(re, obi))
- {
- RayObject *obj = makeraytree_object(re, obi);
- RE_rayobject_add( re->raytree, obj );
-
- if(re->test_break(re->tbh))
- break;
- }
-
- if(!re->test_break(re->tbh))
- {
- RE_rayobject_done( re->raytree );
- }
-
- re->i.infostr= NULL;
- re->stats_draw(re->sdh, &re->i);
-}
-
static int has_special_rayobject(Render *re, ObjectInstanceRen *obi)
{
if( (obi->flag & R_TRANSFORMED) )
@@ -337,10 +312,7 @@ static void makeraytree_single(Render *re)
}
//Create raytree
- if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE)
- raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
- else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH)
- raytree = re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces );
+ raytree = re->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces );
face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");
@@ -385,32 +357,8 @@ void makeraytree(Render *re)
{
float min[3], max[3], sub[3];
int i;
- const char *tree_type = "Tree(unknown)";
- re->r.raystructure = R_RAYSTRUCTURE_SINGLE_BVH;
-#ifdef RE_RAYCOUNTER
- if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BVH)
- tree_type = "BVH";
- if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BIH)
- tree_type = "BIH";
- if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BLIBVH)
- tree_type = "BLIBVH";
-
- if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE)
- printf("Building single octree\n");
- else if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH)
- printf("Building single tree(%s)\n", tree_type);
- else if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE)
- printf("Building tree(%s) of octrees\n", tree_type);
- else
- printf("Building tree(%s) of trees(%s)\n", tree_type, tree_type);
-#endif
-
- if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE))
- BENCH(makeraytree_single(re), tree_build);
- else
- BENCH(makeraytree_hier(re), tree_build);
-
+ BENCH(makeraytree_single(re), tree_build);
//Calculate raytree max_size
//This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights