blender/intern/cycles/kernel/geom/motion_curve.h
Brecht Van Lommel 406577e0d6 Fix #160052: Cycles: Performance regression with CUDA + Blackwell + BVH2
Store positions as separate arrays again. This appears to give better
memory access patterns or layout. This was a regression from fc9917352b
and 0baa98866c.

This is a relatively simple change, rerouting the position attribute to
dedicated arrays, still including motion steps in the same array. The rest
of the refactor is preserved.

Pull Request: https://projects.blender.org/blender/blender/pulls/160110
2026-06-23 12:33:04 +02:00

142 lines
5.3 KiB
C

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "kernel/globals.h"
#include "kernel/bvh/util.h"
CCL_NAMESPACE_BEGIN
/* Motion Curve Primitive
*
* These are stored as regular curves, plus extra positions and radii at times
* other than the frame center. Computing the curve keys at a given ray time is
* a matter of interpolation of the two steps between which the ray time lies.
*
* The extra curve keys are stored as additional motion steps in ATTR_STD_POSITION.
*/
#ifdef __HAIR__
ccl_device_inline void motion_curve_keys_for_step_linear(KernelGlobals kg,
int offset,
const int numverts,
const int numsteps,
int step,
const int k0,
const int k1,
float4 keys[2])
{
const int center_step = (numsteps - 1) / 2;
if (step == center_step) {
/* Center step: first in the array. */
}
else {
/* Non-center step, stored after center with center index skipped. */
if (step < center_step) {
step++;
}
offset += step * numverts;
}
keys[0] = kernel_data_fetch(curve_keys, offset + k0);
keys[1] = kernel_data_fetch(curve_keys, offset + k1);
}
/* return 2 curve key locations */
ccl_device_inline void motion_curve_keys_linear(KernelGlobals kg,
const int object,
const float time,
const int k0,
const int k1,
float4 keys[2])
{
/* get motion info */
const int numsteps = kernel_data_fetch(objects, object).num_geom_steps;
const int numverts = kernel_data_fetch(objects, object).numverts;
/* figure out which steps we need to fetch and their interpolation factor */
const int maxstep = numsteps - 1;
const int step = min((int)(time * maxstep), maxstep - 1);
const float t = time * maxstep - step;
/* fetch key coordinates */
const int offset = kernel_data_fetch(objects, object).position_offset;
float4 next_keys[2];
motion_curve_keys_for_step_linear(kg, offset, numverts, numsteps, step, k0, k1, keys);
motion_curve_keys_for_step_linear(kg, offset, numverts, numsteps, step + 1, k0, k1, next_keys);
/* interpolate between steps */
keys[0] = (1.0f - t) * keys[0] + t * next_keys[0];
keys[1] = (1.0f - t) * keys[1] + t * next_keys[1];
}
ccl_device_inline void motion_curve_keys_for_step(KernelGlobals kg,
int offset,
const int numverts,
const int numsteps,
int step,
const int k0,
const int k1,
const int k2,
const int k3,
float4 keys[4])
{
const int center_step = (numsteps - 1) / 2;
if (step == center_step) {
/* Center step: first in the array. */
}
else {
/* Non-center step, stored after center with center index skipped. */
if (step < center_step) {
step++;
}
offset += step * numverts;
}
keys[0] = kernel_data_fetch(curve_keys, offset + k0);
keys[1] = kernel_data_fetch(curve_keys, offset + k1);
keys[2] = kernel_data_fetch(curve_keys, offset + k2);
keys[3] = kernel_data_fetch(curve_keys, offset + k3);
}
/* return 2 curve key locations */
ccl_device_inline void motion_curve_keys(KernelGlobals kg,
const int object,
const float time,
const int k0,
const int k1,
const int k2,
const int k3,
float4 keys[4])
{
/* get motion info */
const int numsteps = kernel_data_fetch(objects, object).num_geom_steps;
const int numverts = kernel_data_fetch(objects, object).numverts;
/* figure out which steps we need to fetch and their interpolation factor */
const int maxstep = numsteps - 1;
const int step = min((int)(time * maxstep), maxstep - 1);
const float t = time * maxstep - step;
/* fetch key coordinates */
const int offset = kernel_data_fetch(objects, object).position_offset;
float4 next_keys[4];
motion_curve_keys_for_step(kg, offset, numverts, numsteps, step, k0, k1, k2, k3, keys);
motion_curve_keys_for_step(kg, offset, numverts, numsteps, step + 1, k0, k1, k2, k3, next_keys);
/* interpolate between steps */
keys[0] = (1.0f - t) * keys[0] + t * next_keys[0];
keys[1] = (1.0f - t) * keys[1] + t * next_keys[1];
keys[2] = (1.0f - t) * keys[2] + t * next_keys[2];
keys[3] = (1.0f - t) * keys[3] + t * next_keys[3];
}
#endif
CCL_NAMESPACE_END