Cycles: Use dedicated debug passes for traversed nodes and intersection tests

This way it's more clear whether some issue is caused by lots of geometry in
the node or by lots of "transparent" BVH nodes.
This commit is contained in:
Sergey Sharybin 2017-01-12 13:44:35 +01:00
parent 8daf02f134
commit 53fa389802
14 changed files with 70 additions and 39 deletions

View File

@ -306,10 +306,12 @@ static PassType get_pass_type(BL::RenderPass& b_pass)
case BL::RenderPass::type_DEBUG:
{
switch(b_pass.debug_type()) {
case BL::RenderPass::debug_type_BVH_TRAVERSAL_STEPS:
return PASS_BVH_TRAVERSAL_STEPS;
case BL::RenderPass::debug_type_BVH_TRAVERSED_NODES:
return PASS_BVH_TRAVERSED_NODES;
case BL::RenderPass::debug_type_BVH_TRAVERSED_INSTANCES:
return PASS_BVH_TRAVERSED_INSTANCES;
case BL::RenderPass::debug_type_BVH_INTERSECTIONS:
return PASS_BVH_INTERSECTIONS;
case BL::RenderPass::debug_type_RAY_BOUNCES:
return PASS_RAY_BOUNCES;
}

View File

@ -213,7 +213,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
--stack_ptr;
}
}
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_NODE();
}
/* if node is leaf, fetch triangle list */
@ -235,7 +235,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
for(; prim_addr < prim_addr2; prim_addr++) {
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
if(triangle_intersect(kg,
&isect_precalc,
@ -264,7 +264,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
for(; prim_addr < prim_addr2; prim_addr++) {
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
if(motion_triangle_intersect(kg,
isect,
@ -296,7 +296,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
for(; prim_addr < prim_addr2; prim_addr++) {
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
bool hit;
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {

View File

@ -50,12 +50,17 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_DEBUG__
# define BVH_DEBUG_INIT() \
do { \
isect->num_traversal_steps = 0; \
isect->num_traversed_nodes = 0; \
isect->num_traversed_instances = 0; \
isect->num_intersections = 0; \
} while(0)
# define BVH_DEBUG_NEXT_STEP() \
# define BVH_DEBUG_NEXT_NODE() \
do { \
++isect->num_traversal_steps; \
++isect->num_traversed_nodes; \
} while(0)
# define BVH_DEBUG_NEXT_INTERSECTION() \
do { \
++isect->num_intersections; \
} while(0)
# define BVH_DEBUG_NEXT_INSTANCE() \
do { \
@ -63,7 +68,8 @@ CCL_NAMESPACE_BEGIN
} while(0)
#else /* __KERNEL_DEBUG__ */
# define BVH_DEBUG_INIT()
# define BVH_DEBUG_NEXT_STEP()
# define BVH_DEBUG_NEXT_NODE()
# define BVH_DEBUG_NEXT_INTERSECTION()
# define BVH_DEBUG_NEXT_INSTANCE()
#endif /* __KERNEL_DEBUG__ */

View File

@ -131,7 +131,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
int child_mask;
ssef dist;
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_NODE();
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(difl != 0.0f) {
@ -326,7 +326,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
for(; prim_addr < prim_addr2; prim_addr++) {
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
if(triangle_intersect(kg,
&isect_precalc,
@ -347,7 +347,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
for(; prim_addr < prim_addr2; prim_addr++) {
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
if(motion_triangle_intersect(kg,
isect,
@ -371,7 +371,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
for(; prim_addr < prim_addr2; prim_addr++) {
BVH_DEBUG_NEXT_STEP();
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
bool hit;
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {

View File

@ -18,8 +18,9 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void debug_data_init(DebugData *debug_data)
{
debug_data->num_bvh_traversal_steps = 0;
debug_data->num_bvh_traversed_nodes = 0;
debug_data->num_bvh_traversed_instances = 0;
debug_data->num_bvh_intersections = 0;
debug_data->num_ray_bounces = 0;
}
@ -30,16 +31,21 @@ ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg,
int sample)
{
int flag = kernel_data.film.pass_flag;
if(flag & PASS_BVH_TRAVERSAL_STEPS) {
kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversal_steps,
if(flag & PASS_BVH_TRAVERSED_NODES) {
kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_nodes,
sample,
debug_data->num_bvh_traversal_steps);
debug_data->num_bvh_traversed_nodes);
}
if(flag & PASS_BVH_TRAVERSED_INSTANCES) {
kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances,
sample,
debug_data->num_bvh_traversed_instances);
}
if(flag & PASS_BVH_INTERSECTIONS) {
kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_intersections,
sample,
debug_data->num_bvh_intersections);
}
if(flag & PASS_RAY_BOUNCES) {
kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces,
sample,

View File

@ -634,8 +634,9 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
#ifdef __KERNEL_DEBUG__
if(state.flag & PATH_RAY_CAMERA) {
debug_data.num_bvh_traversal_steps += isect.num_traversal_steps;
debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
debug_data.num_bvh_intersections += isect.num_intersections;
}
debug_data.num_ray_bounces++;
#endif /* __KERNEL_DEBUG__ */

View File

@ -288,8 +288,9 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#endif /* __HAIR__ */
#ifdef __KERNEL_DEBUG__
debug_data.num_bvh_traversal_steps += isect.num_traversal_steps;
debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
debug_data.num_bvh_intersections += isect.num_intersections;
debug_data.num_ray_bounces++;
#endif /* __KERNEL_DEBUG__ */

View File

@ -345,9 +345,10 @@ typedef enum PassType {
PASS_SUBSURFACE_COLOR = (1 << 24),
PASS_LIGHT = (1 << 25), /* no real pass, used to force use_light_pass */
#ifdef __KERNEL_DEBUG__
PASS_BVH_TRAVERSAL_STEPS = (1 << 26),
PASS_BVH_TRAVERSED_NODES = (1 << 26),
PASS_BVH_TRAVERSED_INSTANCES = (1 << 27),
PASS_RAY_BOUNCES = (1 << 28),
PASS_BVH_INTERSECTIONS = (1 << 28),
PASS_RAY_BOUNCES = (1 << 29),
#endif
} PassType;
@ -542,8 +543,9 @@ typedef ccl_addr_space struct Intersection {
int type;
#ifdef __KERNEL_DEBUG__
int num_traversal_steps;
int num_traversed_nodes;
int num_traversed_instances;
int num_intersections;
#endif
} Intersection;
@ -1040,10 +1042,10 @@ typedef struct KernelFilm {
float mist_falloff;
#ifdef __KERNEL_DEBUG__
int pass_bvh_traversal_steps;
int pass_bvh_traversed_nodes;
int pass_bvh_traversed_instances;
int pass_bvh_intersections;
int pass_ray_bounces;
int pass_pad3;
#endif
} KernelFilm;
static_assert_align(KernelFilm, 16);
@ -1188,10 +1190,9 @@ static_assert_align(KernelData, 16);
* really important here.
*/
typedef ccl_addr_space struct DebugData {
// Total number of BVH node traversal steps and primitives intersections
// for the camera rays.
int num_bvh_traversal_steps;
int num_bvh_traversed_nodes;
int num_bvh_traversed_instances;
int num_bvh_intersections;
int num_ray_bounces;
} DebugData;
#endif

View File

@ -116,8 +116,9 @@ ccl_device void kernel_scene_intersect(
#ifdef __KERNEL_DEBUG__
if(state.flag & PATH_RAY_CAMERA) {
debug_data->num_bvh_traversal_steps += isect->num_traversal_steps;
debug_data->num_bvh_traversed_nodes += isect->num_traversed_nodes;
debug_data->num_bvh_traversed_instances += isect->num_traversed_instances;
debug_data->num_bvh_intersections += isect->num_intersections;
}
debug_data->num_ray_bounces++;
#endif

View File

@ -185,8 +185,9 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
}
}
#ifdef WITH_CYCLES_DEBUG
else if(type == PASS_BVH_TRAVERSAL_STEPS ||
else if(type == PASS_BVH_TRAVERSED_NODES ||
type == PASS_BVH_TRAVERSED_INSTANCES ||
type == PASS_BVH_INTERSECTIONS ||
type == PASS_RAY_BOUNCES)
{
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {

View File

@ -154,8 +154,9 @@ void Pass::add(PassType type, array<Pass>& passes)
pass.components = 0;
break;
#ifdef WITH_CYCLES_DEBUG
case PASS_BVH_TRAVERSAL_STEPS:
case PASS_BVH_TRAVERSED_NODES:
case PASS_BVH_TRAVERSED_INSTANCES:
case PASS_BVH_INTERSECTIONS:
case PASS_RAY_BOUNCES:
pass.components = 1;
pass.exposure = false;
@ -415,12 +416,15 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
break;
#ifdef WITH_CYCLES_DEBUG
case PASS_BVH_TRAVERSAL_STEPS:
kfilm->pass_bvh_traversal_steps = kfilm->pass_stride;
case PASS_BVH_TRAVERSED_NODES:
kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
break;
case PASS_BVH_TRAVERSED_INSTANCES:
kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
break;
case PASS_BVH_INTERSECTIONS:
kfilm->pass_bvh_intersections = kfilm->pass_stride;
break;
case PASS_RAY_BOUNCES:
kfilm->pass_ray_bounces = kfilm->pass_stride;
break;

View File

@ -78,9 +78,14 @@ EnumPropertyItem rna_enum_render_pass_type_items[] = {
};
EnumPropertyItem rna_enum_render_pass_debug_type_items[] = {
{RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS, "BVH_TRAVERSAL_STEPS", 0, "BVH Traversal Steps", ""},
{RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances", ""},
{RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps", ""},
{RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES, "BVH_TRAVERSED_NODES", 0, "BVH Traversed Nodes",
"Number of nodes traversed in BVH for the camera rays"},
{RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances",
"Number of BVH instances traversed by camera rays"},
{RENDER_PASS_DEBUG_BVH_INTERSECTIONS, "BVH_INTERSECTIONS", 0, "BVH Intersections",
"Number of primitive intersections performed by the camera rays"},
{RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps",
"Number of bounces done by the main integration loop"},
{0, NULL, 0, NULL, NULL}
};

View File

@ -97,9 +97,10 @@ typedef struct RenderPass {
} RenderPass;
enum {
RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS = 0,
RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES = 0,
RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1,
RENDER_PASS_DEBUG_RAY_BOUNCES = 2,
RENDER_PASS_DEBUG_BVH_INTERSECTIONS = 3,
};
/* a renderlayer is a full image, but with all passes and samples */

View File

@ -550,10 +550,12 @@ RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int pas
const char *RE_debug_pass_name_get(int debug_type)
{
switch (debug_type) {
case RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS:
return "BVH Traversal Steps";
case RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES:
return "BVH Traversed Nodes";
case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES:
return "BVH Traversed Instances";
case RENDER_PASS_DEBUG_BVH_INTERSECTIONS:
return "BVH Primitive Intersections";
case RENDER_PASS_DEBUG_RAY_BOUNCES:
return "Ray Bounces";
}