Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instanced attribute sets #91

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
18 changes: 18 additions & 0 deletions src/kernel/geom/geom_attribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg,
desc.type = (NodeAttributeType)(attr_map.w & 0xff);
desc.flags = (AttributeFlag)(attr_map.w >> 8);

/* Offset the index by the instance number */
if (desc.flags & ATTR_INSTANCED) {
const int instance_index = kernel_tex_fetch(__objects, sd->object).instance_index;

if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
desc.offset += instance_index * kernel_tex_fetch(__objects, sd->object).numverts;
} else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_MOTION) {
/* todo(Edoardo): Implement once we have internal subdivision surfaces */
desc.offset += instance_index * kernel_tex_fetch(__objects, sd->object).numfaces * 3;
} else if (desc.element == ATTR_ELEMENT_FACE) {
desc.offset += instance_index * kernel_tex_fetch(__objects, sd->object).numfaces;
} else if (desc.element == ATTR_ELEMENT_CURVE_KEY) {
desc.offset += instance_index * kernel_tex_fetch(__objects, sd->object).numkeys;
} else {
desc.offset += instance_index;
}
}

return desc;
}

Expand Down
12 changes: 6 additions & 6 deletions src/kernel/geom/geom_motion_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ ccl_device_inline int find_attribute_point_motion(KernelGlobals *kg,

ccl_device_inline float4 motion_point_attribute_for_step(KernelGlobals *kg,
int offset,
int numkeys,
int numverts,
int numsteps,
int step,
int prim,
Expand All @@ -62,7 +62,7 @@ ccl_device_inline float4 motion_point_attribute_for_step(KernelGlobals *kg,
if (step > numsteps)
step--;

offset += step * numkeys;
offset += step * numverts;

return kernel_tex_fetch(__attributes_float3, offset + prim);
}
Expand All @@ -78,8 +78,8 @@ ccl_device_inline float4 motion_point_attribute(KernelGlobals *kg,
int attr)
{
/* get motion info */
int numsteps, numkeys;
object_motion_info(kg, object, &numsteps, NULL, &numkeys);
int numsteps, numverts;
object_motion_info(kg, object, &numsteps, &numverts, NULL);

/* figure out which steps we need to fetch and their interpolation factor */
int maxstep = numsteps * 2;
Expand All @@ -93,9 +93,9 @@ ccl_device_inline float4 motion_point_attribute(KernelGlobals *kg,

/* fetch key coordinates */
float4 point_attr = motion_point_attribute_for_step(
kg, offset, numkeys, numsteps, step, prim, n_points_attrs, attr);
kg, offset, numverts, numsteps, step, prim, n_points_attrs, attr);
float4 next_point_attr = motion_point_attribute_for_step(
kg, offset, numkeys, numsteps, step + 1, prim, n_points_attrs, attr);
kg, offset, numverts, numsteps, step + 1, prim, n_points_attrs, attr);

/* interpolate between steps */
return (1.0f - t) * point_attr + t * next_point_attr;
Expand Down
6 changes: 4 additions & 2 deletions src/kernel/kernel_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ typedef enum AttributeStandard {
typedef enum AttributeFlag {
ATTR_FINAL_SIZE = (1 << 0),
ATTR_SUBDIVIDED = (1 << 1),
ATTR_INSTANCED = (1 << 2)
} AttributeFlag;

typedef struct AttributeDescriptor {
Expand Down Expand Up @@ -1534,10 +1535,12 @@ typedef struct KernelObject {
float dupli_uv[2];

int numkeys;
int numverts;
int numverts; /* Number of vertices in a mesh or points in a cloud */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I have problems wrapping my head around this PR to understand what is going on. How numkeys is different than numverts and why numfaceshas been added. I suspect that keys are actually vertices for curves? And why numfaces is important for instancing. Is because we want to override face attributes?

Copy link
Contributor Author

@dedoardo dedoardo Jul 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the goal is to override attributes with different interpolation (or element in cycles speak). If an attribute has ATTR_ELEMENT_VERTEX interpolation, we want to bump the offset by the number of vertices.
The current code was using numkeys for points in a cloud, while attributes authored on those point have ATTR_ELEMENT_VERTEX as interpolation. If we wanted to branch on the type of geometry to calculate the indexed offset, the code would have to be scattered and duplicated in the various primitive_*_attribute. I decided to make that change to streamline the logic.

So far numkeys/numverts was being used for motion blur positions, so faces wasn't needed until now. I know that on the delegate side we currently only support constants, but the USD point instancer specification doesn't impose this limit so I went for a more generic approach. And for completeness.

Copy link
Contributor Author

@dedoardo dedoardo Jul 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are talking about the fact that numkeys and numverts are never set together and we could avoid using one of them, I totally agree. It hasn't been done in this PR to limit the number of changes as it would require patching more parts of the code.

int numfaces;
uint16_t num_tfm_steps;
uint16_t num_dfm_steps;

uint instance_index;
uint patch_map_offset;
uint attribute_map_offset;
uint motion_offset;
Expand All @@ -1549,7 +1552,6 @@ typedef struct KernelObject {
float cryptomatte_asset;

float shadow_terminator_offset;
float pad1, pad2;
} KernelObject;
static_assert_align(KernelObject, 16);

Expand Down
16 changes: 10 additions & 6 deletions src/render/attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ CCL_NAMESPACE_BEGIN
/* Attribute */

Attribute::Attribute(
ustring name, TypeDesc type, AttributeElement element, Geometry *geom, AttributePrimitive prim)
: name(name), std(ATTR_STD_NONE), type(type), element(element), flags(0)
ustring name, TypeDesc type, AttributeElement element, Geometry *geom, AttributePrimitive prim, size_t instances)
: name(name), std(ATTR_STD_NONE), type(type), element(element), flags(0), instances(instances)
{
/* string and matrix not supported! */
assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
Expand All @@ -44,6 +44,10 @@ Attribute::Attribute(
else {
resize(geom, prim, false);
}

if (instances > 1) {
flags |= ATTR_INSTANCED;
}
}

Attribute::~Attribute()
Expand Down Expand Up @@ -164,7 +168,7 @@ size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const

size_t Attribute::buffer_size(Geometry *geom, AttributePrimitive prim) const
{
return element_size(geom, prim) * data_sizeof();
return element_size(geom, prim) * data_sizeof() * instances;
}

bool Attribute::same_storage(TypeDesc a, TypeDesc b)
Expand Down Expand Up @@ -328,8 +332,8 @@ void Attribute::get_uv_tiles(Geometry *geom,

/* Attribute Set */

AttributeSet::AttributeSet(Geometry *geometry, AttributePrimitive prim)
: geometry(geometry), prim(prim)
AttributeSet::AttributeSet(Geometry *geometry, AttributePrimitive prim, size_t instances)
: geometry(geometry), prim(prim), instances(instances)
{
}

Expand All @@ -350,7 +354,7 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
remove(name);
}

Attribute new_attr(name, type, element, geometry, prim);
Attribute new_attr(name, type, element, geometry, prim, instances);
attributes.emplace_back(std::move(new_attr));
return &attributes.back();
}
Expand Down
15 changes: 13 additions & 2 deletions src/render/attribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ class Attribute {
TypeDesc type,
AttributeElement element,
Geometry *geom,
AttributePrimitive prim);
AttributePrimitive prim,
size_t instances = 1);
Attribute(Attribute &&other) = default;
Attribute(const Attribute &other) = delete;
Attribute &operator=(const Attribute &other) = delete;
Expand All @@ -70,6 +71,7 @@ class Attribute {

size_t data_sizeof() const;
size_t element_size(Geometry *geom, AttributePrimitive prim) const;
size_t instances_size() const { return instances; }
size_t buffer_size(Geometry *geom, AttributePrimitive prim) const;

char *data()
Expand Down Expand Up @@ -164,6 +166,10 @@ class Attribute {
static AttributeStandard name_standard(const char *name);

void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set<int> &tiles) const;

private:
/* Multiplier on the size of the buffer */
size_t instances;
};

/* Attribute Set
Expand All @@ -176,7 +182,7 @@ class AttributeSet {
AttributePrimitive prim;
list<Attribute> attributes;

AttributeSet(Geometry *geometry, AttributePrimitive prim);
AttributeSet(Geometry *geometry, AttributePrimitive prim, size_t instances = 1);
~AttributeSet();

Attribute *add(ustring name, TypeDesc type, AttributeElement element);
Expand All @@ -193,6 +199,11 @@ class AttributeSet {

void resize(bool reserve_only = false);
void clear(bool preserve_voxel_data = false);

size_t instances_size() const { return instances; }

private:
size_t instances;
};

/* AttributeRequest
Expand Down
Loading