Refactor: Cycles: Avoid unsafe memcpy and memcmp

Pull Request: https://projects.blender.org/blender/blender/pulls/132361
This commit is contained in:
Brecht Van Lommel
2024-12-27 21:50:31 +01:00
parent da5251f06c
commit 689633d802
24 changed files with 121 additions and 100 deletions

View File

@@ -638,8 +638,7 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node)
* coordinates as generated coordinates if requested */
if (mesh->need_attribute(state.scene, ATTR_STD_GENERATED)) {
Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
memcpy(
attr->data_float3(), mesh->get_verts().data(), sizeof(float3) * mesh->get_verts().size());
std::copy_n(mesh->get_verts().data(), mesh->get_verts().size(), attr->data_float3());
}
}

View File

@@ -2,6 +2,7 @@
*
* SPDX-License-Identifier: Apache-2.0 */
#include <algorithm>
#include <optional>
#include "blender/attribute_convert.h"
@@ -1265,12 +1266,12 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
VLOG_DEBUG << "Filling deformation motion for object " << ob_name;
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
float3 *P = mesh->get_verts().data();
float3 *N = (attr_N) ? attr_N->data_float3() : nullptr;
const float3 *P = mesh->get_verts().data();
const float3 *N = (attr_N) ? attr_N->data_float3() : nullptr;
for (int step = 0; step < motion_step; step++) {
memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts);
std::copy_n(P, numverts, attr_mP->data_float3() + step * numverts);
if (attr_mN) {
memcpy(attr_mN->data_float3() + step * numverts, N, sizeof(float3) * numverts);
std::copy_n(N, numverts, attr_mN->data_float3() + step * numverts);
}
}
}
@@ -1279,9 +1280,11 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
if (b_verts_num != numverts) {
VLOG_WARNING << "Topology differs, discarding motion blur for object " << ob_name
<< " at time " << motion_step;
memcpy(mP, mesh->get_verts().data(), sizeof(float3) * numverts);
const float3 *P = mesh->get_verts().data();
const float3 *N = (attr_N) ? attr_N->data_float3() : nullptr;
std::copy_n(P, numverts, mP);
if (mN != nullptr) {
memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts);
std::copy_n(N, numverts, mN);
}
}
}

View File

@@ -449,7 +449,7 @@ bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance
changed = true;
attributes.push_back(new_param);
}
else if (memcmp(param->data(), &value, sizeof(value)) != 0) {
else if (!(param->get<float4>() == value)) {
changed = true;
*param = new_param;
}

View File

@@ -360,15 +360,22 @@ static inline void render_add_metadata(BL::RenderResult &b_rr, string name, stri
static inline Transform get_transform(const BL::Array<float, 16> &array)
{
ProjectionTransform projection;
/* Convert from Blender column major to Cycles row major, assume it's an affine transform that
* does not need the last row. */
return make_transform(array[0],
array[4],
array[8],
array[12],
/* We assume both types to be just 16 floats, and transpose because blender
* use column major matrix order while we use row major. */
memcpy((void *)&projection, &array, sizeof(float) * 16);
projection = projection_transpose(projection);
array[1],
array[5],
array[9],
array[13],
/* Drop last row, matrix is assumed to be affine transform. */
return projection_to_transform(projection);
array[2],
array[6],
array[10],
array[14]);
}
static inline float2 get_float2(const BL::Array<float, 2> &array)

View File

@@ -5,6 +5,8 @@
*
* Adapted code from NVIDIA Corporation. */
#include <algorithm>
#include "bvh/bvh2.h"
#include "scene/hair.h"
@@ -107,24 +109,24 @@ BVHNode *BVH2::widen_children_nodes(const BVHNode *root)
void BVH2::pack_leaf(const BVHStackEntry &e, const LeafNode *leaf)
{
assert(e.idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
float4 data[BVH_NODE_LEAF_SIZE];
memset(data, 0, sizeof(data));
int4 data[BVH_NODE_LEAF_SIZE];
std::fill_n(data, BVH_NODE_LEAF_SIZE, zero_int4());
if (leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
/* object */
data[0].x = __int_as_float(~(leaf->lo));
data[0].y = __int_as_float(0);
data[0].x = ~(leaf->lo);
data[0].y = 0;
}
else {
/* triangle */
data[0].x = __int_as_float(leaf->lo);
data[0].y = __int_as_float(leaf->hi);
data[0].x = leaf->lo;
data[0].y = leaf->hi;
}
data[0].z = __uint_as_float(leaf->visibility);
data[0].z = leaf->visibility;
if (leaf->num_triangles() != 0) {
data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
data[0].w = pack.prim_type[leaf->lo];
}
memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4) * BVH_NODE_LEAF_SIZE);
std::copy_n(data, BVH_NODE_LEAF_SIZE, &pack.leaf_nodes[e.idx]);
}
void BVH2::pack_inner(const BVHStackEntry &e, const BVHStackEntry &e0, const BVHStackEntry &e1)
@@ -179,7 +181,7 @@ void BVH2::pack_aligned_node(int idx,
__float_as_int(b1.max.z)),
};
memcpy(&pack.nodes[idx], data, sizeof(int4) * BVH_NODE_SIZE);
std::copy_n(data, BVH_NODE_SIZE, &pack.nodes[idx]);
}
void BVH2::pack_unaligned_inner(const BVHStackEntry &e,
@@ -211,22 +213,20 @@ void BVH2::pack_unaligned_node(int idx,
assert(c0 < 0 || c0 < pack.nodes.size());
assert(c1 < 0 || c1 < pack.nodes.size());
float4 data[BVH_UNALIGNED_NODE_SIZE];
int4 data[BVH_UNALIGNED_NODE_SIZE];
Transform space0 = BVHUnaligned::compute_node_transform(b0, aligned_space0);
Transform space1 = BVHUnaligned::compute_node_transform(b1, aligned_space1);
data[0] = make_float4(__int_as_float(visibility0 | PATH_RAY_NODE_UNALIGNED),
__int_as_float(visibility1 | PATH_RAY_NODE_UNALIGNED),
__int_as_float(c0),
__int_as_float(c1));
data[0] = make_int4(
visibility0 | PATH_RAY_NODE_UNALIGNED, visibility1 | PATH_RAY_NODE_UNALIGNED, c0, c1);
data[1] = space0.x;
data[2] = space0.y;
data[3] = space0.z;
data[4] = space1.x;
data[5] = space1.y;
data[6] = space1.z;
data[1] = __float4_as_int4(space0.x);
data[2] = __float4_as_int4(space0.y);
data[3] = __float4_as_int4(space0.z);
data[4] = __float4_as_int4(space1.x);
data[5] = __float4_as_int4(space1.y);
data[6] = __float4_as_int4(space1.z);
memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_UNALIGNED_NODE_SIZE);
std::copy_n(data, BVH_UNALIGNED_NODE_SIZE, &pack.nodes[idx]);
}
void BVH2::pack_nodes(const BVHNode *root)
@@ -323,12 +323,12 @@ void BVH2::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
refit_primitives(c0, c1, bbox, visibility);
/* TODO(sergey): De-duplicate with pack_leaf(). */
float4 leaf_data[BVH_NODE_LEAF_SIZE];
leaf_data[0].x = __int_as_float(c0);
leaf_data[0].y = __int_as_float(c1);
leaf_data[0].z = __uint_as_float(visibility);
leaf_data[0].w = __uint_as_float(data[0].w);
memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_NODE_LEAF_SIZE);
int4 leaf_data[BVH_NODE_LEAF_SIZE];
leaf_data[0].x = c0;
leaf_data[0].y = c1;
leaf_data[0].z = visibility;
leaf_data[0].w = data[0].w;
std::copy_n(leaf_data, BVH_NODE_LEAF_SIZE, &pack.leaf_nodes[idx]);
}
else {
assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
@@ -628,7 +628,7 @@ void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
nsize_bbox = 0;
}
memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox * sizeof(int4));
std::copy_n(bvh_nodes + i, nsize_bbox, pack_nodes + pack_nodes_offset);
/* Modify offsets into arrays */
int4 data = bvh_nodes[i + nsize_bbox];
@@ -639,9 +639,9 @@ void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
/* Usually this copies nothing, but we better
* be prepared for possible node size extension.
*/
memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox + 1],
&bvh_nodes[i + nsize_bbox + 1],
sizeof(int4) * (nsize - (nsize_bbox + 1)));
std::copy_n(&bvh_nodes[i + nsize_bbox + 1],
(nsize - (nsize_bbox + 1)),
&pack_nodes[pack_nodes_offset + nsize_bbox + 1]);
pack_nodes_offset += nsize;
i += nsize;

View File

@@ -565,7 +565,7 @@ void BVHEmbree::set_point_vertex_buffer(RTCGeometry geom_id,
/* Motion blur is already packed as [x y z radius]. */
int t_ = (t > t_mid) ? (t - 1) : t;
const float4 *verts = &attr_mP->data_float4()[t_ * num_points];
memcpy(rtc_verts, verts, sizeof(float4) * num_points);
std::copy_n(verts, num_points, rtc_verts);
}
}

View File

@@ -226,16 +226,7 @@ class BVHReference {
return time_to_;
}
BVHReference &operator=(const BVHReference &arg)
{
if (&arg != this) {
/* TODO(sergey): Check if it is still faster to memcpy() with
* modern compilers.
*/
memcpy((void *)this, &arg, sizeof(BVHReference));
}
return *this;
}
BVHReference &operator=(const BVHReference &arg) = default;
protected:
BoundBox rbounds;

View File

@@ -193,7 +193,6 @@ device_texture::device_texture(Device *device,
return;
}
memset(&info, 0, sizeof(info));
info.data_type = image_data_type;
info.interpolation = interpolation;
info.extension = extension;

View File

@@ -618,7 +618,7 @@ class device_texture : public device_memory {
void *alloc(const size_t width, const size_t height, const size_t depth = 0);
void copy_to_device();
uint slot;
uint slot = 0;
TextureInfo info;
protected:

View File

@@ -4,6 +4,7 @@
#ifdef WITH_METAL
# include <algorithm>
# include <chrono>
# include <thread>
# include <vector>
@@ -211,7 +212,7 @@ bool BVHMetal::build_BLAS_mesh(Progress &progress,
if (step != center_step) {
verts = motion_keys->data_float3() + (step > center_step ? step - 1 : step) * num_verts;
}
memcpy(dest_data + num_verts * step, verts, num_verts * sizeof(float3));
std::copy_n(verts, num_verts, dest_data + num_verts * step);
}
if (storage_mode == MTLResourceStorageModeManaged) {
[posBuf didModifyRange:NSMakeRange(0, posBuf.length)];

View File

@@ -340,7 +340,7 @@ void ShaderCache::load_kernel(DeviceKernel device_kernel,
* to be active. */
pipeline->pipeline_id = g_next_pipeline_id.fetch_add(1);
pipeline->originating_device_id = device->device_id;
memcpy(&pipeline->kernel_data_, &device->launch_params.data, sizeof(pipeline->kernel_data_));
pipeline->kernel_data_ = device->launch_params.data;
pipeline->pso_type = pso_type;
pipeline->mtlDevice = mtlDevice;
pipeline->kernels_md5 = device->kernels_md5[pso_type];

View File

@@ -144,9 +144,9 @@ void osl_eval_nodes<SHADER_TYPE_SURFACE>(const KernelGlobalsCPU *kg,
assert(found);
differential3 tmp_dP;
memcpy(&sd->P, data, sizeof(float) * 3);
memcpy(&tmp_dP.dx, data + 3, sizeof(float) * 3);
memcpy(&tmp_dP.dy, data + 6, sizeof(float) * 3);
sd->P = make_float3(data[0], data[1], data[2]);
tmp_dP.dx = make_float3(data[3], data[4], data[5]);
tmp_dP.dy = make_float3(data[6], data[7], data[8]);
object_position_transform(kg, sd, &sd->P);
object_dir_transform(kg, sd, &tmp_dP.dx);

View File

@@ -46,13 +46,13 @@ CCL_NAMESPACE_BEGIN
static void copy_matrix(OSL::Matrix44 &m, const Transform &tfm)
{
ProjectionTransform t = projection_transpose(ProjectionTransform(tfm));
memcpy((void *)&m, &t, sizeof(m));
memcpy((float *)&m, (const float *)&t, sizeof(m));
}
static void copy_matrix(OSL::Matrix44 &m, const ProjectionTransform &tfm)
{
ProjectionTransform t = projection_transpose(tfm);
memcpy((void *)&m, &t, sizeof(m));
memcpy((float *)&m, (const float *)&t, sizeof(m));
}
/* static ustrings */
@@ -743,7 +743,9 @@ static bool get_object_attribute(const KernelGlobalsCPU *kg,
else
#endif
{
memset(fval, 0, sizeof(fval));
fval[0] = zero_float3();
fval[1] = zero_float3();
fval[2] = zero_float3();
fval[0] = primitive_surface_attribute_float3(
kg, sd, desc, (derivatives) ? &fval[1] : nullptr, (derivatives) ? &fval[2] : nullptr);
}
@@ -781,7 +783,9 @@ static bool get_object_attribute(const KernelGlobalsCPU *kg,
float4 fval[3];
#ifdef __VOLUME__
if (primitive_is_volume_attribute(sd, desc)) {
memset(fval, 0, sizeof(fval));
fval[0] = zero_float4();
fval[1] = zero_float4();
fval[2] = zero_float4();
fval[0] = primitive_volume_attribute_float4(kg, sd, desc);
}
else

View File

@@ -2,8 +2,10 @@
*
* SPDX-License-Identifier: Apache-2.0 */
#include "scene/alembic_read.h"
#include <algorithm>
#include "scene/alembic.h"
#include "scene/alembic_read.h"
#include "scene/mesh.h"
#include "util/color.h"
@@ -112,7 +114,7 @@ static void compute_vertex_normals(CachedData &cache, double current_time)
array<char> attr_data(vertices->size() * sizeof(float3));
float3 *attr_ptr = reinterpret_cast<float3 *>(attr_data.data());
memset(attr_ptr, 0, vertices->size() * sizeof(float3));
std::fill_n(attr_ptr, vertices->size(), zero_float3());
for (size_t t = 0; t < triangles->size(); ++t) {
const int3 tri_int3 = triangles->data()[t];

View File

@@ -2,6 +2,8 @@
*
* SPDX-License-Identifier: Apache-2.0 */
#include <algorithm>
#include "scene/camera.h"
#include "scene/mesh.h"
#include "scene/object.h"
@@ -514,7 +516,7 @@ void Camera::device_update(Device * /*device*/, DeviceScene *dscene, Scene *scen
size_t num_motion_steps = kernel_camera_motion.size();
if (num_motion_steps) {
DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps);
memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps);
std::copy_n(kernel_camera_motion.data(), num_motion_steps, camera_motion);
dscene->camera_motion.copy_to_device();
}
else {
@@ -779,8 +781,7 @@ float Camera::world_to_raster_size(float3 P)
float3 D = transform_point(&worldtocamera, P);
float dist = len(D);
Ray ray;
memset(&ray, 0, sizeof(ray));
Ray ray = {};
/* Distortion can become so great that the results become meaningless, there
* may be a better way to do this, but calculating differentials from the

View File

@@ -2,6 +2,8 @@
*
* SPDX-License-Identifier: Apache-2.0 */
#include <algorithm>
#include "bvh/bvh.h"
#include "scene/curves.h"
@@ -352,7 +354,7 @@ void Hair::copy_center_to_motion_step(const int motion_step)
if (attr_mP) {
float3 *keys = curve_keys.data();
size_t numkeys = curve_keys.size();
memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys);
std::copy_n(keys, numkeys, attr_mP->data_float3() + motion_step * numkeys);
}
}

View File

@@ -2,6 +2,8 @@
*
* SPDX-License-Identifier: Apache-2.0 */
#include <algorithm>
#include "bvh/build.h"
#include "bvh/bvh.h"
@@ -425,9 +427,9 @@ void Mesh::copy_center_to_motion_step(const int motion_step)
float3 *N = (attr_N) ? attr_N->data_float3() : nullptr;
size_t numverts = verts.size();
memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts);
std::copy_n(P, numverts, attr_mP->data_float3() + motion_step * numverts);
if (attr_mN) {
memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts);
std::copy_n(N, numverts, attr_mN->data_float3() + motion_step * numverts);
}
}
}
@@ -585,7 +587,7 @@ void Mesh::add_vertex_normals()
float3 *vN = attr_vN->data_float3();
/* compute vertex normals */
memset(vN, 0, verts.size() * sizeof(float3));
std::fill_n(vN, verts.size(), zero_float3());
for (size_t i = 0; i < triangles_size; i++) {
for (size_t j = 0; j < 3; j++) {
@@ -618,7 +620,7 @@ void Mesh::add_vertex_normals()
float3 *mN = attr_mN->data_float3() + step * verts.size();
/* compute */
memset(mN, 0, verts.size() * sizeof(float3));
std::fill_n(mN, verts.size(), zero_float3());
for (size_t i = 0; i < triangles_size; i++) {
Triangle tri = get_triangle(i);
@@ -648,7 +650,7 @@ void Mesh::add_vertex_normals()
float3 *vN = attr_vN->data_float3();
/* compute vertex normals */
memset(vN, 0, verts.size() * sizeof(float3));
std::fill_n(vN, verts.size(), zero_float3());
for (size_t i = 0; i < get_num_subd_faces(); i++) {
SubdFace face = get_subd_face(i);
@@ -689,16 +691,16 @@ void Mesh::add_undisplaced()
float3 *data = attr->data_float3();
/* copy verts */
size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY);
size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY) / sizeof(float3);
/* Center points for ngons aren't stored in Mesh::verts but are included in size since they will
* be calculated later, we subtract them from size here so we don't have an overflow while
* copying.
*/
size -= num_ngons * attr->data_sizeof();
size -= num_ngons;
if (size) {
memcpy(data, verts.data(), size);
std::copy_n(verts.data(), size, data);
}
}

View File

@@ -54,7 +54,7 @@ void ParticleSystemManager::device_update_particles(Device * /*unused*/,
KernelParticle *kparticles = dscene->particles.alloc(num_particles);
/* dummy particle */
memset(kparticles, 0, sizeof(KernelParticle));
*kparticles = KernelParticle{};
int i = 1;
for (size_t j = 0; j < scene->particle_systems.size(); j++) {

View File

@@ -2,6 +2,8 @@
*
* SPDX-License-Identifier: Apache-2.0 */
#include <algorithm>
#include "device/device.h"
#include "scene/background.h"
@@ -124,7 +126,7 @@ void SVMShaderManager::device_update_specific(Device *device,
for (int i = 0; i < num_shaders; i++) {
int shader_size = shader_svm_nodes[i].size() - 1;
memcpy(svm_nodes, &shader_svm_nodes[i][1], sizeof(int4) * shader_size);
std::copy_n(&shader_svm_nodes[i][1], shader_size, svm_nodes);
svm_nodes += shader_size;
}

View File

@@ -54,7 +54,7 @@ typedef struct _stat path_stat_t;
# define S_ISDIR(x) (((x) & _S_IFDIR) == _S_IFDIR)
# endif
#else
typedef struct stat path_stat_t;
using path_stat_t = struct stat;
#endif
static string cached_path;

View File

@@ -208,8 +208,8 @@ ccl_device_inline ProjectionTransform projection_inverse(const ProjectionTransfo
ProjectionTransform tfmR = projection_identity();
float M[4][4], R[4][4];
memcpy(R, &tfmR, sizeof(R));
memcpy(M, &tfm, sizeof(M));
memcpy(R, (const float *)&tfmR, sizeof(R));
memcpy(M, (const float *)&tfm, sizeof(M));
if (UNLIKELY(!projection_inverse_impl(R, M))) {
return projection_identity();

View File

@@ -19,7 +19,7 @@ enum {
/* Interpolation types for textures
* CUDA also use texture space to store other objects. */
enum InterpolationType {
INTERPOLATION_NONE = -1,
INTERPOLATION_NONE = ~0,
INTERPOLATION_LINEAR = 0,
INTERPOLATION_CLOSEST = 1,
INTERPOLATION_CUBIC = 2,
@@ -75,16 +75,19 @@ enum ExtensionType {
struct TextureInfo {
/* Pointer, offset or texture depending on device. */
uint64_t data;
uint64_t data = 0;
/* Data Type */
uint data_type;
uint data_type = IMAGE_DATA_NUM_TYPES;
/* Interpolation and extension type. */
uint interpolation, extension;
uint interpolation = INTERPOLATION_NONE;
uint extension = EXTENSION_REPEAT;
/* Dimensions. */
uint width, height, depth;
uint width = 0;
uint height = 0;
uint depth = 0;
/* Transform for 3D textures. */
uint use_transform_3d;
Transform transform_3d;
uint use_transform_3d = false;
Transform transform_3d = transform_zero();
};
CCL_NAMESPACE_END

View File

@@ -224,14 +224,14 @@ ccl_device_inline Transform operator*(const Transform a, const Transform b)
}
#endif
#ifndef __KERNEL_GPU__
ccl_device_inline Transform transform_zero()
{
Transform zero = {zero_float4(), zero_float4(), zero_float4()};
return zero;
}
#ifndef __KERNEL_GPU__
ccl_device_inline void print_transform(const char *label, const Transform &t)
{
print_float4(label, t.x);
@@ -299,7 +299,7 @@ ccl_device_inline Transform transform_identity()
ccl_device_inline bool operator==(const Transform &A, const Transform &B)
{
return memcmp(&A, &B, sizeof(Transform)) == 0;
return A.x == B.x && A.y == B.y && A.z == B.z;
}
ccl_device_inline bool operator!=(const Transform &A, const Transform &B)
@@ -518,7 +518,7 @@ class BoundBox2D;
ccl_device_inline bool operator==(const DecomposedTransform &A, const DecomposedTransform &B)
{
return memcmp(&A, &B, sizeof(DecomposedTransform)) == 0;
return A.x == B.x && A.y == B.y && A.z == B.z && A.w == B.w;
}
float4 transform_to_quat(const Transform &tfm);

View File

@@ -77,6 +77,11 @@ ccl_device_inline int4 make_int4(int i)
#endif
}
ccl_device_inline int4 zero_int4()
{
return make_int4(0);
}
ccl_device_inline void print_int4(ccl_private const char *label, const int4 a)
{
#ifdef __KERNEL_PRINTF__