Refactor: Payload for shadow intersection and filter in HIP-RT
The code before this change was relying on the ShadowPayload have the same "header" as RayPayload for some of the primitive types (curve, motion triangle, point): intersection functions were shared between "regular" and shadow rays (shadow in this case is shadow_all), but extra filter function was used for shadow rays. This is fragile if someone changes one of these structures. What is worse is that compiler might actually decide to shuffle things in some structs, or remove unused fields. This change also solves confusion about ShadowPayload::prim_type seemingly only being assigned to PRIMITIVE_NONE. With time it is not impossible that compiler will also see this, and constant-fold some checks, or even remove the field. If that happens then the render result will be wrong. Maybe it is already happening as there are some GPU and driver and optimization flag specific bugs in the area. It is unclear whether it was causing any actual problem: W7800 seems to render all hair correctly on Linux.
This commit is contained in:
committed by
Sergey Sharybin
parent
cdb3f34944
commit
e92a8042c3
@@ -181,13 +181,13 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals kg,
|
||||
SET_HIPRT_RAY(ray_hip, ray)
|
||||
|
||||
ShadowPayload payload;
|
||||
payload.kg = kg;
|
||||
payload.self = ray->self;
|
||||
payload.ray.kg = kg;
|
||||
payload.ray.self = ray->self;
|
||||
payload.ray.visibility = visibility;
|
||||
payload.ray.prim_type = PRIMITIVE_NONE;
|
||||
payload.ray.ray_time = ray->time;
|
||||
payload.in_state = state;
|
||||
payload.max_hits = max_hits;
|
||||
payload.visibility = visibility;
|
||||
payload.prim_type = PRIMITIVE_NONE;
|
||||
payload.ray_time = ray->time;
|
||||
payload.num_hits = 0;
|
||||
payload.r_num_recorded_hits = num_recorded_hits;
|
||||
payload.r_throughput = throughput;
|
||||
|
||||
@@ -13,11 +13,12 @@ struct RayPayload {
|
||||
};
|
||||
|
||||
struct ShadowPayload {
|
||||
KernelGlobals kg;
|
||||
RaySelfPrimitives self;
|
||||
uint visibility;
|
||||
int prim_type;
|
||||
float ray_time;
|
||||
/* Some ray types might use the same intersection function for regular and shadow intersections,
|
||||
* but have different filter functions for them. To make this code simpler essentially subclass
|
||||
* from RayPayload, but let compiler to possibly shuffle things inside of the payload struct if
|
||||
* it decides it helps performance. */
|
||||
RayPayload ray;
|
||||
|
||||
int in_state;
|
||||
uint max_hits;
|
||||
uint num_hits;
|
||||
@@ -377,12 +378,12 @@ ccl_device_inline bool shadow_intersection_filter(const hiprtRay &ray,
|
||||
const hiprtHit &hit)
|
||||
|
||||
{
|
||||
KernelGlobals kg = payload->kg;
|
||||
KernelGlobals kg = payload->ray.kg;
|
||||
|
||||
const uint num_hits = payload->num_hits;
|
||||
const uint max_hits = payload->max_hits;
|
||||
const int state = payload->in_state;
|
||||
const RaySelfPrimitives self = payload->self;
|
||||
const RaySelfPrimitives self = payload->ray.self;
|
||||
|
||||
const int object = kernel_data_fetch(user_instance_id, hit.instanceID);
|
||||
const int prim_offset = kernel_data_fetch(object_prim_offset, object);
|
||||
@@ -397,7 +398,7 @@ ccl_device_inline bool shadow_intersection_filter(const hiprtRay &ray,
|
||||
# endif
|
||||
|
||||
# ifdef __VISIBILITY_FLAG__
|
||||
if ((kernel_data_fetch(objects, object).visibility & payload->visibility) == 0) {
|
||||
if ((kernel_data_fetch(objects, object).visibility & payload->ray.visibility) == 0) {
|
||||
return true; /* No hit - continue traversal. */
|
||||
}
|
||||
# endif
|
||||
@@ -464,12 +465,12 @@ ccl_device_inline bool shadow_intersection_filter_curves(const hiprtRay &ray,
|
||||
const hiprtHit &hit)
|
||||
|
||||
{
|
||||
KernelGlobals kg = payload->kg;
|
||||
KernelGlobals kg = payload->ray.kg;
|
||||
|
||||
const uint num_hits = payload->num_hits;
|
||||
const uint num_recorded_hits = *(payload->r_num_recorded_hits);
|
||||
const uint max_hits = payload->max_hits;
|
||||
const RaySelfPrimitives self = payload->self;
|
||||
const RaySelfPrimitives self = payload->ray.self;
|
||||
|
||||
const int object = kernel_data_fetch(user_instance_id, hit.instanceID);
|
||||
const int prim = hit.primID;
|
||||
@@ -484,7 +485,7 @@ ccl_device_inline bool shadow_intersection_filter_curves(const hiprtRay &ray,
|
||||
# endif
|
||||
|
||||
# ifdef __VISIBILITY_FLAG__
|
||||
if ((kernel_data_fetch(objects, object).visibility & payload->visibility) == 0) {
|
||||
if ((kernel_data_fetch(objects, object).visibility & payload->ray.visibility) == 0) {
|
||||
return true; /* No hit - continue traversal. */
|
||||
}
|
||||
# endif
|
||||
@@ -504,7 +505,7 @@ ccl_device_inline bool shadow_intersection_filter_curves(const hiprtRay &ray,
|
||||
return true; /* Continue traversal. */
|
||||
}
|
||||
|
||||
const int primitive_type = payload->prim_type;
|
||||
const int primitive_type = payload->ray.prim_type;
|
||||
|
||||
# ifndef __TRANSPARENT_SHADOWS__
|
||||
return false;
|
||||
@@ -611,18 +612,21 @@ HIPRT_DEVICE bool intersectFunc(const uint geom_type,
|
||||
const uint index = tableHeader.numGeomTypes * ray_type + geom_type;
|
||||
switch (index) {
|
||||
case Curve_Intersect_Function:
|
||||
case Curve_Intersect_Shadow:
|
||||
return curve_custom_intersect(ray, (RayPayload *)payload, hit);
|
||||
case Curve_Intersect_Shadow:
|
||||
return curve_custom_intersect(ray, &((ShadowPayload *)payload)->ray, hit);
|
||||
case Motion_Triangle_Intersect_Function:
|
||||
case Motion_Triangle_Intersect_Shadow:
|
||||
return motion_triangle_custom_intersect(ray, (RayPayload *)payload, hit);
|
||||
case Motion_Triangle_Intersect_Shadow:
|
||||
return motion_triangle_custom_intersect(ray, &((ShadowPayload *)payload)->ray, hit);
|
||||
case Motion_Triangle_Intersect_Local:
|
||||
return motion_triangle_custom_local_intersect(ray, (LocalPayload *)payload, hit);
|
||||
case Motion_Triangle_Intersect_Volume:
|
||||
return motion_triangle_custom_volume_intersect(ray, (RayPayload *)payload, hit);
|
||||
case Point_Intersect_Function:
|
||||
case Point_Intersect_Shadow:
|
||||
return point_custom_intersect(ray, (RayPayload *)payload, hit);
|
||||
case Point_Intersect_Shadow:
|
||||
return point_custom_intersect(ray, &((ShadowPayload *)payload)->ray, hit);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user