Fix Cycles HIP RT issues with deformation motion blur
The first problem was triangles with motion blur were all grouped into one category without separating the ones with and without triangle motion steps. The second problem was HIP RT uses the generic motion triangle intersection function and this function checks prim_visibility buffer. HIP RT doesn't provide the buffer per primitive but passes it to HIP RT core per instance. The buffer name was changed to prim_visibility from visibility to be the same as what Cycles uses but when the motion triangle intersection function is called from HIP RT kernels, the instance id is passed to the function instead of primitive id. Pull Request: https://projects.blender.org/blender/blender/pulls/114555
This commit is contained in:
committed by
Brecht Van Lommel
parent
b670e7a82c
commit
13171183fa
@@ -65,7 +65,7 @@ HIPRTDevice::HIPRTDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
|
||||
functions_table(NULL),
|
||||
scratch_buffer_size(0),
|
||||
scratch_buffer(this, "scratch_buffer", MEM_DEVICE_ONLY),
|
||||
visibility(this, "visibility", MEM_READ_ONLY),
|
||||
prim_visibility(this, "prim_visibility", MEM_GLOBAL),
|
||||
instance_transform_matrix(this, "instance_transform_matrix", MEM_READ_ONLY),
|
||||
transform_headers(this, "transform_headers", MEM_READ_ONLY),
|
||||
user_instance_id(this, "user_instance_id", MEM_GLOBAL),
|
||||
@@ -104,7 +104,7 @@ HIPRTDevice::~HIPRTDevice()
|
||||
{
|
||||
HIPContextScope scope(this);
|
||||
user_instance_id.free();
|
||||
visibility.free();
|
||||
prim_visibility.free();
|
||||
hiprt_blas_ptr.free();
|
||||
blas_ptr.free();
|
||||
instance_transform_matrix.free();
|
||||
@@ -388,54 +388,72 @@ hiprtGeometryBuildInput HIPRTDevice::prepare_triangle_blas(BVHHIPRT *bvh, Mesh *
|
||||
hiprtGeometryBuildInput geom_input;
|
||||
geom_input.geomType = Triangle;
|
||||
|
||||
if (mesh->has_motion_blur() &&
|
||||
!(bvh->params.num_motion_triangle_steps == 0 || bvh->params.use_spatial_split))
|
||||
{
|
||||
if (mesh->has_motion_blur()) {
|
||||
|
||||
const Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
const float3 *vert_steps = attr_mP->data_float3();
|
||||
const size_t num_verts = mesh->get_verts().size();
|
||||
const size_t num_steps = mesh->get_motion_steps();
|
||||
const size_t num_triangles = mesh->num_triangles();
|
||||
|
||||
const int num_bvh_steps = bvh->params.num_motion_triangle_steps * 2 + 1;
|
||||
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
|
||||
|
||||
const float3 *verts = mesh->get_verts().data();
|
||||
int num_bounds = 0;
|
||||
bvh->custom_primitive_bound.alloc(num_triangles * num_bvh_steps);
|
||||
|
||||
for (uint j = 0; j < num_triangles; j++) {
|
||||
Mesh::Triangle t = mesh->get_triangle(j);
|
||||
const float3 *verts = mesh->get_verts().data();
|
||||
if (bvh->params.num_motion_triangle_steps == 0 || bvh->params.use_spatial_split) {
|
||||
bvh->custom_primitive_bound.alloc(num_triangles);
|
||||
bvh->custom_prim_info.resize(num_triangles);
|
||||
for (uint j = 0; j < num_triangles; j++) {
|
||||
Mesh::Triangle t = mesh->get_triangle(j);
|
||||
BoundBox bounds = BoundBox::empty;
|
||||
t.bounds_grow(verts, bounds);
|
||||
for (size_t step = 0; step < num_steps - 1; step++) {
|
||||
t.bounds_grow(vert_steps + step * num_verts, bounds);
|
||||
}
|
||||
|
||||
const size_t num_verts = mesh->get_verts().size();
|
||||
const size_t num_steps = mesh->get_motion_steps();
|
||||
const float3 *vert_steps = attr_mP->data_float3();
|
||||
|
||||
float3 prev_verts[3];
|
||||
t.motion_verts(verts, vert_steps, num_verts, num_steps, 0.0f, prev_verts);
|
||||
BoundBox prev_bounds = BoundBox::empty;
|
||||
prev_bounds.grow(prev_verts[0]);
|
||||
prev_bounds.grow(prev_verts[1]);
|
||||
prev_bounds.grow(prev_verts[2]);
|
||||
|
||||
for (int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
|
||||
const float curr_time = (float)(bvh_step)*num_bvh_steps_inv_1;
|
||||
float3 curr_verts[3];
|
||||
t.motion_verts(verts, vert_steps, num_verts, num_steps, curr_time, curr_verts);
|
||||
BoundBox curr_bounds = BoundBox::empty;
|
||||
curr_bounds.grow(curr_verts[0]);
|
||||
curr_bounds.grow(curr_verts[1]);
|
||||
curr_bounds.grow(curr_verts[2]);
|
||||
BoundBox bounds = prev_bounds;
|
||||
bounds.grow(curr_bounds);
|
||||
if (bounds.valid()) {
|
||||
const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
|
||||
bvh->custom_primitive_bound[num_bounds] = bounds;
|
||||
bvh->custom_prim_info[num_bounds].x = j;
|
||||
bvh->custom_prim_info[num_bounds].y = mesh->primitive_type();
|
||||
bvh->prims_time[num_bounds].x = curr_time;
|
||||
bvh->prims_time[num_bounds].y = prev_time;
|
||||
num_bounds++;
|
||||
}
|
||||
prev_bounds = curr_bounds;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const int num_bvh_steps = bvh->params.num_motion_triangle_steps * 2 + 1;
|
||||
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
|
||||
|
||||
bvh->custom_primitive_bound.alloc(num_triangles * num_bvh_steps);
|
||||
bvh->custom_prim_info.resize(num_triangles * num_bvh_steps);
|
||||
|
||||
for (uint j = 0; j < num_triangles; j++) {
|
||||
Mesh::Triangle t = mesh->get_triangle(j);
|
||||
float3 prev_verts[3];
|
||||
t.motion_verts(verts, vert_steps, num_verts, num_steps, 0.0f, prev_verts);
|
||||
BoundBox prev_bounds = BoundBox::empty;
|
||||
prev_bounds.grow(prev_verts[0]);
|
||||
prev_bounds.grow(prev_verts[1]);
|
||||
prev_bounds.grow(prev_verts[2]);
|
||||
|
||||
for (int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
|
||||
const float curr_time = (float)(bvh_step)*num_bvh_steps_inv_1;
|
||||
float3 curr_verts[3];
|
||||
t.motion_verts(verts, vert_steps, num_verts, num_steps, curr_time, curr_verts);
|
||||
BoundBox curr_bounds = BoundBox::empty;
|
||||
curr_bounds.grow(curr_verts[0]);
|
||||
curr_bounds.grow(curr_verts[1]);
|
||||
curr_bounds.grow(curr_verts[2]);
|
||||
BoundBox bounds = prev_bounds;
|
||||
bounds.grow(curr_bounds);
|
||||
if (bounds.valid()) {
|
||||
const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
|
||||
bvh->custom_primitive_bound[num_bounds] = bounds;
|
||||
bvh->custom_prim_info[num_bounds].x = j;
|
||||
bvh->custom_prim_info[num_bounds].y = mesh->primitive_type();
|
||||
bvh->prims_time[num_bounds].x = curr_time;
|
||||
bvh->prims_time[num_bounds].y = prev_time;
|
||||
num_bounds++;
|
||||
}
|
||||
prev_bounds = curr_bounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,7 +467,6 @@ hiprtGeometryBuildInput HIPRTDevice::prepare_triangle_blas(BVHHIPRT *bvh, Mesh *
|
||||
geom_input.geomType = Motion_Triangle;
|
||||
}
|
||||
else {
|
||||
|
||||
size_t triangle_size = mesh->get_triangles().size();
|
||||
void *triangle_data = mesh->get_triangles().data();
|
||||
|
||||
@@ -480,6 +497,7 @@ hiprtGeometryBuildInput HIPRTDevice::prepare_triangle_blas(BVHHIPRT *bvh, Mesh *
|
||||
geom_input.type = hiprtPrimitiveTypeTriangleMesh;
|
||||
geom_input.triangleMesh.primitive = &(bvh->triangle_mesh);
|
||||
}
|
||||
|
||||
return geom_input;
|
||||
}
|
||||
|
||||
@@ -800,7 +818,7 @@ hiprtScene HIPRTDevice::build_tlas(BVHHIPRT *bvh,
|
||||
|
||||
size_t num_object = objects.size();
|
||||
user_instance_id.alloc(num_object);
|
||||
visibility.alloc(num_object);
|
||||
prim_visibility.alloc(num_object);
|
||||
hiprt_blas_ptr.alloc(num_object);
|
||||
blas_ptr.alloc(num_object);
|
||||
transform_headers.alloc(num_object);
|
||||
@@ -913,7 +931,7 @@ hiprtScene HIPRTDevice::build_tlas(BVHHIPRT *bvh,
|
||||
transform_headers[num_instances] = current_header;
|
||||
|
||||
user_instance_id[num_instances] = blender_instance_id;
|
||||
visibility[num_instances] = mask;
|
||||
prim_visibility[num_instances] = mask;
|
||||
hiprt_blas_ptr[num_instances] = (uint64_t)hiprt_geom_current;
|
||||
num_instances++;
|
||||
}
|
||||
@@ -928,7 +946,7 @@ hiprtScene HIPRTDevice::build_tlas(BVHHIPRT *bvh,
|
||||
scene_input_ptr.frameType = hiprtFrameTypeMatrix;
|
||||
|
||||
user_instance_id.copy_to_device();
|
||||
visibility.copy_to_device();
|
||||
prim_visibility.copy_to_device();
|
||||
hiprt_blas_ptr.copy_to_device();
|
||||
blas_ptr.copy_to_device();
|
||||
transform_headers.copy_to_device();
|
||||
@@ -942,7 +960,7 @@ hiprtScene HIPRTDevice::build_tlas(BVHHIPRT *bvh,
|
||||
instance_transform_matrix.host_pointer = 0;
|
||||
}
|
||||
|
||||
scene_input_ptr.instanceMasks = (void *)visibility.device_pointer;
|
||||
scene_input_ptr.instanceMasks = (void *)prim_visibility.device_pointer;
|
||||
scene_input_ptr.instanceGeometries = (void *)hiprt_blas_ptr.device_pointer;
|
||||
scene_input_ptr.instanceTransformHeaders = (void *)transform_headers.device_pointer;
|
||||
scene_input_ptr.instanceFrames = (void *)instance_transform_matrix.device_pointer;
|
||||
|
||||
@@ -82,7 +82,11 @@ class HIPRTDevice : public HIPDevice {
|
||||
* are defined on the GPU side as members of KernelParamsHIPRT struct the host memory is copied
|
||||
* to GPU through const_copy_to() function. */
|
||||
|
||||
device_vector<uint32_t> visibility;
|
||||
/* Originally, visibility was only passed to HIP RT but after a bug report it was noted it was
|
||||
* required for custom primitives (i.e., motion triangles). This buffer, however, has visibility
|
||||
* per object not per primitive so the same buffer as the one that is passed to HIP RT can be
|
||||
* used. */
|
||||
device_vector<uint32_t> prim_visibility;
|
||||
|
||||
/* instance_transform_matrix passes transform matrix of instances converted from Cycles Transform
|
||||
* format to instanceFrames member of hiprtSceneBuildInput. */
|
||||
|
||||
@@ -177,7 +177,6 @@ ccl_device_inline bool motion_triangle_custom_intersect(const hiprtRay &ray,
|
||||
void *payload,
|
||||
hiprtHit &hit)
|
||||
{
|
||||
# ifdef MOTION_BLUR
|
||||
RayPayload *local_payload = (RayPayload *)payload;
|
||||
KernelGlobals kg = local_payload->kg;
|
||||
int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
|
||||
@@ -202,7 +201,7 @@ ccl_device_inline bool motion_triangle_custom_intersect(const hiprtRay &ray,
|
||||
local_payload->visibility,
|
||||
object_id,
|
||||
prim_id_global,
|
||||
prim_id_local);
|
||||
hit.instanceID);
|
||||
|
||||
if (b_hit) {
|
||||
hit.uv.x = isect.u;
|
||||
@@ -212,9 +211,6 @@ ccl_device_inline bool motion_triangle_custom_intersect(const hiprtRay &ray,
|
||||
local_payload->prim_type = isect.type;
|
||||
}
|
||||
return b_hit;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
ccl_device_inline bool motion_triangle_custom_local_intersect(const hiprtRay &ray,
|
||||
|
||||
Reference in New Issue
Block a user