Cleanup: Cycles: Deduplicate code in geometry_attributes.cpp

#134644 would make this even worse, so it's time to clean up a bit.

Pull Request: https://projects.blender.org/blender/blender/pulls/134645
This commit is contained in:
Lukas Stockner
2025-02-23 16:34:34 +01:00
parent 44d6ff6f8b
commit e6839df2a3
3 changed files with 111 additions and 216 deletions

View File

@@ -274,23 +274,6 @@ class GeometryManager {
void device_update_displacement_images(Device *device, Scene *scene, Progress &progress);
void device_update_volume_images(Device *device, Scene *scene, Progress &progress);
private:
static void update_attribute_element_offset(Geometry *geom,
device_vector<float> &attr_float,
size_t &attr_float_offset,
device_vector<float2> &attr_float2,
size_t &attr_float2_offset,
device_vector<packed_float3> &attr_float3,
size_t &attr_float3_offset,
device_vector<float4> &attr_float4,
size_t &attr_float4_offset,
device_vector<uchar4> &attr_uchar4,
size_t &attr_uchar4_offset,
Attribute *mattr,
AttributePrimitive prim,
TypeDesc &type,
AttributeDescriptor &desc);
};
CCL_NAMESPACE_END

View File

@@ -270,23 +270,67 @@ void GeometryManager::update_svm_attributes(Device * /*unused*/,
dscene->attributes_map.copy_to_device();
}
void GeometryManager::update_attribute_element_offset(Geometry *geom,
device_vector<float> &attr_float,
size_t &attr_float_offset,
device_vector<float2> &attr_float2,
size_t &attr_float2_offset,
device_vector<packed_float3> &attr_float3,
size_t &attr_float3_offset,
device_vector<float4> &attr_float4,
size_t &attr_float4_offset,
device_vector<uchar4> &attr_uchar4,
size_t &attr_uchar4_offset,
Attribute *mattr,
AttributePrimitive prim,
TypeDesc &type,
AttributeDescriptor &desc)
{
if (mattr) {
template<typename T> struct AttributeTableEntry {
device_vector<T> &data;
size_t offset;
size_t size;
void reserve(const size_t attr_size)
{
size += attr_size;
}
/* Templated on U since we'll want to assign float3 values to a packed_float3 device_vector. */
template<typename U> size_t add(const U *attr_data, const size_t attr_size, const bool modified)
{
assert(data.size() >= offset + attr_size);
size_t start_offset = offset;
if (modified) {
for (size_t k = 0; k < attr_size; k++) {
data[offset + k] = attr_data[k];
}
data.tag_modified();
}
offset += attr_size;
return start_offset;
}
void alloc()
{
data.alloc(size);
}
};
class AttributeTableBuilder {
public:
AttributeTableBuilder(DeviceScene *dscene)
: attr_float{dscene->attributes_float, 0, 0},
attr_float2{dscene->attributes_float2, 0, 0},
attr_float3{dscene->attributes_float3, 0, 0},
attr_float4{dscene->attributes_float4, 0, 0},
attr_uchar4{dscene->attributes_uchar4, 0, 0}
{
}
AttributeTableEntry<float> attr_float;
AttributeTableEntry<float2> attr_float2;
AttributeTableEntry<packed_float3> attr_float3;
AttributeTableEntry<float4> attr_float4;
AttributeTableEntry<uchar4> attr_uchar4;
void add(Geometry *geom,
Attribute *mattr,
AttributePrimitive prim,
TypeDesc &type,
AttributeDescriptor &desc)
{
if (mattr == nullptr) {
/* attribute not found */
desc.element = ATTR_ELEMENT_NONE;
desc.offset = 0;
return;
}
/* store element and type */
desc.element = mattr->element;
desc.flags = mattr->flags;
@@ -304,89 +348,29 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
offset = handle.svm_slot();
}
else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
uchar4 *data = mattr->data_uchar4();
offset = attr_uchar4_offset;
assert(attr_uchar4.size() >= offset + size);
if (mattr->modified) {
for (size_t k = 0; k < size; k++) {
attr_uchar4[offset + k] = data[k];
}
attr_uchar4.tag_modified();
}
attr_uchar4_offset += size;
offset = attr_uchar4.add(mattr->data_uchar4(), size, mattr->modified);
}
else if (mattr->type == TypeFloat) {
float *data = mattr->data_float();
offset = attr_float_offset;
assert(attr_float.size() >= offset + size);
if (mattr->modified) {
for (size_t k = 0; k < size; k++) {
attr_float[offset + k] = data[k];
}
attr_float.tag_modified();
}
attr_float_offset += size;
offset = attr_float.add(mattr->data_float(), size, mattr->modified);
}
else if (mattr->type == TypeFloat2) {
float2 *data = mattr->data_float2();
offset = attr_float2_offset;
assert(attr_float2.size() >= offset + size);
if (mattr->modified) {
for (size_t k = 0; k < size; k++) {
attr_float2[offset + k] = data[k];
}
attr_float2.tag_modified();
}
attr_float2_offset += size;
offset = attr_float2.add(mattr->data_float2(), size, mattr->modified);
}
else if (mattr->type == TypeMatrix) {
Transform *tfm = mattr->data_transform();
offset = attr_float4_offset;
assert(attr_float4.size() >= offset + size * 3);
if (mattr->modified) {
for (size_t k = 0; k < size * 3; k++) {
attr_float4[offset + k] = (&tfm->x)[k];
}
attr_float4.tag_modified();
}
attr_float4_offset += size * 3;
offset = attr_float4.add((float4 *)mattr->data_transform(), size * 3, mattr->modified);
}
else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
float4 *data = mattr->data_float4();
offset = attr_float4_offset;
assert(attr_float4.size() >= offset + size);
if (mattr->modified) {
for (size_t k = 0; k < size; k++) {
attr_float4[offset + k] = data[k];
}
attr_float4.tag_modified();
}
attr_float4_offset += size;
offset = attr_float4.add(mattr->data_float4(), size, mattr->modified);
}
else {
float3 *data = mattr->data_float3();
offset = attr_float3_offset;
assert(attr_float3.size() >= offset + size);
if (mattr->modified) {
for (size_t k = 0; k < size; k++) {
attr_float3[offset + k] = data[k];
}
attr_float3.tag_modified();
}
attr_float3_offset += size;
offset = attr_float3.add(mattr->data_float3(), size, mattr->modified);
}
/* mesh vertex/curve index is global, not per object, so we sneak
* a correction for that in here */
if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
if (mesh->get_subdivision_type() == Mesh::SUBDIVISION_CATMULL_CLARK &&
desc.flags & ATTR_SUBDIVIDED)
{
/* Indices for subdivided attributes are retrieved
@@ -436,48 +420,56 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
}
}
}
else {
/* attribute not found */
desc.element = ATTR_ELEMENT_NONE;
desc.offset = 0;
}
}
static void update_attribute_element_size(Geometry *geom,
Attribute *mattr,
AttributePrimitive prim,
size_t *attr_float_size,
size_t *attr_float2_size,
size_t *attr_float3_size,
size_t *attr_float4_size,
size_t *attr_uchar4_size)
{
if (mattr) {
void reserve(Geometry *geom, Attribute *mattr, AttributePrimitive prim)
{
if (mattr == nullptr) {
return;
}
const size_t size = mattr->element_size(geom, prim);
if (mattr->element == ATTR_ELEMENT_VOXEL) {
/* pass */
}
else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
*attr_uchar4_size += size;
attr_uchar4.reserve(size);
}
else if (mattr->type == TypeFloat) {
*attr_float_size += size;
attr_float.reserve(size);
}
else if (mattr->type == TypeFloat2) {
*attr_float2_size += size;
attr_float2.reserve(size);
}
else if (mattr->type == TypeMatrix) {
*attr_float4_size += size * 4;
attr_float4.reserve(size * 3);
}
else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
*attr_float4_size += size;
attr_float4.reserve(size);
}
else {
*attr_float3_size += size;
attr_float3.reserve(size);
}
}
}
void alloc()
{
attr_float.alloc();
attr_float2.alloc();
attr_float3.alloc();
attr_float4.alloc();
attr_uchar4.alloc();
}
void copy_to_device_if_modified()
{
attr_float.data.copy_to_device_if_modified();
attr_float2.data.copy_to_device_if_modified();
attr_float3.data.copy_to_device_if_modified();
attr_float4.data.copy_to_device_if_modified();
attr_uchar4.data.copy_to_device_if_modified();
}
};
void GeometryManager::device_update_attributes(Device *device,
DeviceScene *dscene,
@@ -547,11 +539,7 @@ void GeometryManager::device_update_attributes(Device *device,
/* Pre-allocate attributes to avoid arrays re-allocation which would
* take 2x of overall attribute memory usage.
*/
size_t attr_float_size = 0;
size_t attr_float2_size = 0;
size_t attr_float3_size = 0;
size_t attr_float4_size = 0;
size_t attr_uchar4_size = 0;
AttributeTableBuilder builder(dscene);
for (size_t i = 0; i < scene->geometry.size(); i++) {
Geometry *geom = scene->geometry[i];
@@ -559,27 +547,13 @@ void GeometryManager::device_update_attributes(Device *device,
for (AttributeRequest &req : attributes.requests) {
Attribute *attr = geom->attributes.find(req);
update_attribute_element_size(geom,
attr,
ATTR_PRIM_GEOMETRY,
&attr_float_size,
&attr_float2_size,
&attr_float3_size,
&attr_float4_size,
&attr_uchar4_size);
builder.reserve(geom, attr, ATTR_PRIM_GEOMETRY);
if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
Attribute *subd_attr = mesh->subd_attributes.find(req);
update_attribute_element_size(mesh,
subd_attr,
ATTR_PRIM_SUBD,
&attr_float_size,
&attr_float2_size,
&attr_float3_size,
&attr_float4_size,
&attr_uchar4_size);
builder.reserve(mesh, subd_attr, ATTR_PRIM_SUBD);
}
}
}
@@ -588,22 +562,11 @@ void GeometryManager::device_update_attributes(Device *device,
Object *object = scene->objects[i];
for (Attribute &attr : object_attribute_values[i].attributes) {
update_attribute_element_size(object->geometry,
&attr,
ATTR_PRIM_GEOMETRY,
&attr_float_size,
&attr_float2_size,
&attr_float3_size,
&attr_float4_size,
&attr_uchar4_size);
builder.reserve(object->geometry, &attr, ATTR_PRIM_GEOMETRY);
}
}
dscene->attributes_float.alloc(attr_float_size);
dscene->attributes_float2.alloc(attr_float2_size);
dscene->attributes_float3.alloc(attr_float3_size);
dscene->attributes_float4.alloc(attr_float4_size);
dscene->attributes_uchar4.alloc(attr_uchar4_size);
builder.alloc();
/* The order of those flags needs to match that of AttrKernelDataType. */
const bool attributes_need_realloc[AttrKernelDataType::NUM] = {
@@ -614,12 +577,6 @@ void GeometryManager::device_update_attributes(Device *device,
dscene->attributes_uchar4.need_realloc(),
};
size_t attr_float_offset = 0;
size_t attr_float2_offset = 0;
size_t attr_float3_offset = 0;
size_t attr_float4_offset = 0;
size_t attr_uchar4_offset = 0;
/* Fill in attributes. */
for (size_t i = 0; i < scene->geometry.size(); i++) {
Geometry *geom = scene->geometry[i];
@@ -635,21 +592,7 @@ void GeometryManager::device_update_attributes(Device *device,
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
}
update_attribute_element_offset(geom,
dscene->attributes_float,
attr_float_offset,
dscene->attributes_float2,
attr_float2_offset,
dscene->attributes_float3,
attr_float3_offset,
dscene->attributes_float4,
attr_float4_offset,
dscene->attributes_uchar4,
attr_uchar4_offset,
attr,
ATTR_PRIM_GEOMETRY,
req.type,
req.desc);
builder.add(geom, attr, ATTR_PRIM_GEOMETRY, req.type, req.desc);
if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
@@ -660,21 +603,7 @@ void GeometryManager::device_update_attributes(Device *device,
subd_attr->modified |= attributes_need_realloc[Attribute::kernel_type(*subd_attr)];
}
update_attribute_element_offset(mesh,
dscene->attributes_float,
attr_float_offset,
dscene->attributes_float2,
attr_float2_offset,
dscene->attributes_float3,
attr_float3_offset,
dscene->attributes_float4,
attr_float4_offset,
dscene->attributes_uchar4,
attr_uchar4_offset,
subd_attr,
ATTR_PRIM_SUBD,
req.subd_type,
req.subd_desc);
builder.add(mesh, subd_attr, ATTR_PRIM_SUBD, req.subd_type, req.subd_desc);
}
if (progress.get_cancel()) {
@@ -695,21 +624,7 @@ void GeometryManager::device_update_attributes(Device *device,
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
}
update_attribute_element_offset(object->geometry,
dscene->attributes_float,
attr_float_offset,
dscene->attributes_float2,
attr_float2_offset,
dscene->attributes_float3,
attr_float3_offset,
dscene->attributes_float4,
attr_float4_offset,
dscene->attributes_uchar4,
attr_uchar4_offset,
attr,
ATTR_PRIM_GEOMETRY,
req.type,
req.desc);
builder.add(object->geometry, attr, ATTR_PRIM_GEOMETRY, req.type, req.desc);
/* object attributes don't care about subdivision */
req.subd_type = req.type;
@@ -735,11 +650,7 @@ void GeometryManager::device_update_attributes(Device *device,
/* copy to device */
progress.set_status("Updating Mesh", "Copying Attributes to device");
dscene->attributes_float.copy_to_device_if_modified();
dscene->attributes_float2.copy_to_device_if_modified();
dscene->attributes_float3.copy_to_device_if_modified();
dscene->attributes_float4.copy_to_device_if_modified();
dscene->attributes_uchar4.copy_to_device_if_modified();
builder.copy_to_device_if_modified();
if (progress.get_cancel()) {
return;

View File

@@ -157,8 +157,6 @@ class Mesh : public Geometry {
AttributeSet subd_attributes;
private:
unique_ptr<PackedPatchTable> patch_table;
/* BVH */
size_t vert_offset;
@@ -167,6 +165,9 @@ class Mesh : public Geometry {
size_t face_offset;
size_t corner_offset;
private:
unique_ptr<PackedPatchTable> patch_table;
size_t num_subd_verts;
size_t num_subd_faces;