Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/geometry.cpp
| Show First 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | bool Geometry::need_attribute(Scene *scene, AttributeStandard std) | ||||
| if (std == ATTR_STD_NONE) | if (std == ATTR_STD_NONE) | ||||
| return false; | return false; | ||||
| if (scene->need_global_attribute(std)) | if (scene->need_global_attribute(std)) | ||||
| return true; | return true; | ||||
| foreach (Node *node, used_shaders) { | foreach (Node *node, used_shaders) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| if (shader->attributes.find(std)) | if (shader->get_attributes().find(std)) | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool Geometry::need_attribute(Scene * /*scene*/, ustring name) | bool Geometry::need_attribute(Scene * /*scene*/, ustring name) | ||||
| { | { | ||||
| if (name == ustring()) | if (name == ustring()) | ||||
| return false; | return false; | ||||
| foreach (Node *node, used_shaders) { | foreach (Node *node, used_shaders) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| if (shader->attributes.find(name)) | if (shader->get_attributes().find(name)) | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| AttributeRequestSet Geometry::needed_attributes() | AttributeRequestSet Geometry::needed_attributes() | ||||
| { | { | ||||
| AttributeRequestSet result; | AttributeRequestSet result; | ||||
| foreach (Node *node, used_shaders) { | foreach (Node *node, used_shaders) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| result.add(shader->attributes); | result.add(shader->get_attributes()); | ||||
| } | } | ||||
| return result; | return result; | ||||
| } | } | ||||
| float Geometry::motion_time(int step) const | float Geometry::motion_time(int step) const | ||||
| { | { | ||||
| return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f; | return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f; | ||||
| Show All 35 Lines | bool Geometry::is_instanced() const | ||||
| */ | */ | ||||
| return !transform_applied || has_surface_bssrdf; | return !transform_applied || has_surface_bssrdf; | ||||
| } | } | ||||
| bool Geometry::has_true_displacement() const | bool Geometry::has_true_displacement() const | ||||
| { | { | ||||
| foreach (Node *node, used_shaders) { | foreach (Node *node, used_shaders) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| if (shader->has_displacement && shader->get_displacement_method() != DISPLACE_BUMP) { | if (shader->get_has_displacement() && shader->get_displacement_method() != DISPLACE_BUMP) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| void Geometry::compute_bvh( | void Geometry::compute_bvh( | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
| bool Geometry::has_motion_blur() const | bool Geometry::has_motion_blur() const | ||||
| { | { | ||||
| return (use_motion_blur && attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)); | return (use_motion_blur && attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)); | ||||
| } | } | ||||
| bool Geometry::has_voxel_attributes() const | bool Geometry::has_voxel_attributes() const | ||||
| { | { | ||||
| foreach (const Attribute &attr, attributes.attributes) { | foreach (const Attribute &attr, attributes.get_attributes()) { | ||||
| if (attr.element == ATTR_ELEMENT_VOXEL) { | if (attr.get_element() == ATTR_ELEMENT_VOXEL) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| void Geometry::tag_update(Scene *scene, bool rebuild) | void Geometry::tag_update(Scene *scene, bool rebuild) | ||||
| { | { | ||||
| tag_modified(); | tag_modified(); | ||||
| if (rebuild) { | if (rebuild) { | ||||
| need_update_rebuild = true; | need_update_rebuild = true; | ||||
| scene->light_manager->need_update = true; | scene->get_light_manager()->need_update = true; | ||||
| } | } | ||||
| else { | else { | ||||
| foreach (Node *node, used_shaders) { | foreach (Node *node, used_shaders) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| if (shader->has_surface_emission) | if (shader->get_has_surface_emission()) | ||||
| scene->light_manager->need_update = true; | scene->get_light_manager()->need_update = true; | ||||
| } | } | ||||
| } | } | ||||
| scene->geometry_manager->need_update = true; | scene->get_geometry_manager()->need_update = true; | ||||
| scene->object_manager->need_update = true; | scene->get_object_manager()->need_update = true; | ||||
| } | } | ||||
| void Geometry::tag_bvh_update(bool rebuild) | void Geometry::tag_bvh_update(bool rebuild) | ||||
| { | { | ||||
| tag_modified(); | tag_modified(); | ||||
| if (rebuild) { | if (rebuild) { | ||||
| need_update_rebuild = true; | need_update_rebuild = true; | ||||
| Show All 19 Lines | |||||
| #ifdef WITH_OSL | #ifdef WITH_OSL | ||||
| /* for OSL, a hash map is used to lookup the attribute by name. */ | /* for OSL, a hash map is used to lookup the attribute by name. */ | ||||
| OSLGlobals *og = (OSLGlobals *)device->osl_memory(); | OSLGlobals *og = (OSLGlobals *)device->osl_memory(); | ||||
| og->object_name_map.clear(); | og->object_name_map.clear(); | ||||
| og->attribute_map.clear(); | og->attribute_map.clear(); | ||||
| og->object_names.clear(); | og->object_names.clear(); | ||||
| og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES); | og->attribute_map.resize(scene->get_objects().size() * ATTR_PRIM_TYPES); | ||||
| for (size_t i = 0; i < scene->objects.size(); i++) { | for (size_t i = 0; i < scene->get_objects().size(); i++) { | ||||
| /* set object name to object index map */ | /* set object name to object index map */ | ||||
| Object *object = scene->objects[i]; | Object *object = scene->get_objects()[i]; | ||||
| og->object_name_map[object->name] = i; | og->object_name_map[object->name] = i; | ||||
| og->object_names.push_back(object->name); | og->object_names.push_back(object->name); | ||||
| /* set object attributes */ | /* set object attributes */ | ||||
| foreach (ParamValue &attr, object->attributes) { | foreach (ParamValue &attr, object->attributes) { | ||||
| OSLGlobals::Attribute osl_attr; | OSLGlobals::Attribute osl_attr; | ||||
| osl_attr.type = attr.type(); | osl_attr.type = attr.type(); | ||||
| osl_attr.desc.element = ATTR_ELEMENT_OBJECT; | osl_attr.desc.element = ATTR_ELEMENT_OBJECT; | ||||
| osl_attr.value = attr; | osl_attr.value = attr; | ||||
| osl_attr.desc.offset = 0; | osl_attr.desc.offset = 0; | ||||
| osl_attr.desc.flags = 0; | osl_attr.desc.flags = 0; | ||||
| og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][attr.name()] = osl_attr; | og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][attr.name()] = osl_attr; | ||||
| og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr; | og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr; | ||||
| } | } | ||||
| /* find geometry attributes */ | /* find geometry attributes */ | ||||
| size_t j = object->geometry->index; | size_t j = object->geometry->get_index(); | ||||
| assert(j < scene->geometry.size() && scene->geometry[j] == object->geometry); | assert(j < scene->get_geometry().size() && scene->get_geometry()[j] == object->geometry); | ||||
| AttributeRequestSet &attributes = geom_attributes[j]; | AttributeRequestSet &attributes = geom_attributes[j]; | ||||
| /* set mesh attributes */ | /* set mesh attributes */ | ||||
| foreach (AttributeRequest &req, attributes.requests) { | foreach (const AttributeRequest &req, attributes.get_requests()) { | ||||
| OSLGlobals::Attribute osl_attr; | OSLGlobals::Attribute osl_attr; | ||||
| if (req.desc.element != ATTR_ELEMENT_NONE) { | if (req.get_desc().element != ATTR_ELEMENT_NONE) { | ||||
| osl_attr.desc = req.desc; | osl_attr.desc = req.get_desc(); | ||||
| if (req.type == TypeDesc::TypeFloat) | if (req.get_type() == TypeDesc::TypeFloat) | ||||
| osl_attr.type = TypeDesc::TypeFloat; | osl_attr.type = TypeDesc::TypeFloat; | ||||
| else if (req.type == TypeDesc::TypeMatrix) | else if (req.get_type() == TypeDesc::TypeMatrix) | ||||
| osl_attr.type = TypeDesc::TypeMatrix; | osl_attr.type = TypeDesc::TypeMatrix; | ||||
| else if (req.type == TypeFloat2) | else if (req.get_type() == TypeFloat2) | ||||
| osl_attr.type = TypeFloat2; | osl_attr.type = TypeFloat2; | ||||
| else if (req.type == TypeRGBA) | else if (req.get_type() == TypeRGBA) | ||||
| osl_attr.type = TypeRGBA; | osl_attr.type = TypeRGBA; | ||||
| else | else | ||||
| osl_attr.type = TypeDesc::TypeColor; | osl_attr.type = TypeDesc::TypeColor; | ||||
| if (req.std != ATTR_STD_NONE) { | if (req.get_std() != ATTR_STD_NONE) { | ||||
| /* if standard attribute, add lookup by geom: name convention */ | /* if standard attribute, add lookup by geom: name convention */ | ||||
| ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); | ustring stdname(string("geom:") + string(Attribute::standard_name(req.get_std()))); | ||||
| og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][stdname] = osl_attr; | og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][stdname] = osl_attr; | ||||
| } | } | ||||
| else if (req.name != ustring()) { | else if (req.get_name() != ustring()) { | ||||
| /* add lookup by geometry attribute name */ | /* add lookup by geometry attribute name */ | ||||
| og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][req.name] = osl_attr; | og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][req.get_name()] = osl_attr; | ||||
| } | } | ||||
| } | } | ||||
| if (req.subd_desc.element != ATTR_ELEMENT_NONE) { | if (req.get_subd_desc().element != ATTR_ELEMENT_NONE) { | ||||
| osl_attr.desc = req.subd_desc; | osl_attr.desc = req.get_subd_desc(); | ||||
| if (req.subd_type == TypeDesc::TypeFloat) | if (req.get_subd_type() == TypeDesc::TypeFloat) | ||||
| osl_attr.type = TypeDesc::TypeFloat; | osl_attr.type = TypeDesc::TypeFloat; | ||||
| else if (req.subd_type == TypeDesc::TypeMatrix) | else if (req.get_subd_type() == TypeDesc::TypeMatrix) | ||||
| osl_attr.type = TypeDesc::TypeMatrix; | osl_attr.type = TypeDesc::TypeMatrix; | ||||
| else if (req.subd_type == TypeFloat2) | else if (req.get_subd_type() == TypeFloat2) | ||||
| osl_attr.type = TypeFloat2; | osl_attr.type = TypeFloat2; | ||||
| else if (req.subd_type == TypeRGBA) | else if (req.get_subd_type() == TypeRGBA) | ||||
| osl_attr.type = TypeRGBA; | osl_attr.type = TypeRGBA; | ||||
| else | else | ||||
| osl_attr.type = TypeDesc::TypeColor; | osl_attr.type = TypeDesc::TypeColor; | ||||
| if (req.std != ATTR_STD_NONE) { | if (req.get_std() != ATTR_STD_NONE) { | ||||
| /* if standard attribute, add lookup by geom: name convention */ | /* if standard attribute, add lookup by geom: name convention */ | ||||
| ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); | ustring stdname(string("geom:") + string(Attribute::standard_name(req.get_std()))); | ||||
| og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr; | og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr; | ||||
| } | } | ||||
| else if (req.name != ustring()) { | else if (req.get_name() != ustring()) { | ||||
| /* add lookup by geometry attribute name */ | /* add lookup by geometry attribute name */ | ||||
| og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr; | og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.get_name()] = osl_attr; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #else | #else | ||||
| (void)device; | (void)device; | ||||
| (void)scene; | (void)scene; | ||||
| (void)geom_attributes; | (void)geom_attributes; | ||||
| Show All 33 Lines | for (int j = 0; j < ATTR_PRIM_TYPES; j++) { | ||||
| attr_map[index + j].y = chain; /* link is valid flag */ | attr_map[index + j].y = chain; /* link is valid flag */ | ||||
| attr_map[index + j].z = chain ? chain_link + j : 0; /* link to the correct sub-entry */ | attr_map[index + j].z = chain ? chain_link + j : 0; /* link to the correct sub-entry */ | ||||
| attr_map[index + j].w = 0; | attr_map[index + j].w = 0; | ||||
| } | } | ||||
| } | } | ||||
| /* Generate all necessary attribute map entries from the attribute request. */ | /* Generate all necessary attribute map entries from the attribute request. */ | ||||
| static void emit_attribute_mapping( | static void emit_attribute_mapping( | ||||
| uint4 *attr_map, int index, Scene *scene, AttributeRequest &req, Geometry *geom) | uint4 *attr_map, int index, Scene *scene, const AttributeRequest &req, Geometry *geom) | ||||
| { | { | ||||
| uint id; | uint id; | ||||
| if (req.std == ATTR_STD_NONE) | if (req.get_std() == ATTR_STD_NONE) | ||||
| id = scene->shader_manager->get_attribute_id(req.name); | id = scene->get_shader_manager()->get_attribute_id(req.get_name()); | ||||
| else | else | ||||
| id = scene->shader_manager->get_attribute_id(req.std); | id = scene->get_shader_manager()->get_attribute_id(req.get_std()); | ||||
| emit_attribute_map_entry(attr_map, index, id, req.type, req.desc); | emit_attribute_map_entry(attr_map, index, id, req.get_type(), req.get_desc()); | ||||
| if (geom->is_mesh()) { | if (geom->is_mesh()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| if (mesh->get_num_subd_faces()) { | if (mesh->get_num_subd_faces()) { | ||||
| emit_attribute_map_entry(attr_map, index + 1, id, req.subd_type, req.subd_desc); | emit_attribute_map_entry(attr_map, index + 1, id, req.get_subd_type(), req.get_subd_desc()); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void GeometryManager::update_svm_attributes(Device *, | void GeometryManager::update_svm_attributes(Device *, | ||||
| DeviceScene *dscene, | DeviceScene *dscene, | ||||
| Scene *scene, | Scene *scene, | ||||
| vector<AttributeRequestSet> &geom_attributes, | vector<AttributeRequestSet> &geom_attributes, | ||||
| vector<AttributeRequestSet> &object_attributes) | vector<AttributeRequestSet> &object_attributes) | ||||
| { | { | ||||
| /* for SVM, the attributes_map table is used to lookup the offset of an | /* for SVM, the attributes_map table is used to lookup the offset of an | ||||
| * attribute, based on a unique shader attribute id. */ | * attribute, based on a unique shader attribute id. */ | ||||
| /* compute array stride */ | /* compute array stride */ | ||||
| int attr_map_size = 0; | int attr_map_size = 0; | ||||
| for (size_t i = 0; i < scene->geometry.size(); i++) { | for (size_t i = 0; i < scene->get_geometry().size(); i++) { | ||||
| Geometry *geom = scene->geometry[i]; | Geometry *geom = scene->get_geometry()[i]; | ||||
| geom->attr_map_offset = attr_map_size; | geom->set_attr_map_offset(attr_map_size); | ||||
| attr_map_size += (geom_attributes[i].size() + 1) * ATTR_PRIM_TYPES; | attr_map_size += (geom_attributes[i].size() + 1) * ATTR_PRIM_TYPES; | ||||
| } | } | ||||
| for (size_t i = 0; i < scene->objects.size(); i++) { | for (size_t i = 0; i < scene->get_objects().size(); i++) { | ||||
| Object *object = scene->objects[i]; | Object *object = scene->get_objects()[i]; | ||||
| /* only allocate a table for the object if it actually has attributes */ | /* only allocate a table for the object if it actually has attributes */ | ||||
| if (object_attributes[i].size() == 0) { | if (object_attributes[i].size() == 0) { | ||||
| object->attr_map_offset = 0; | object->attr_map_offset = 0; | ||||
| } | } | ||||
| else { | else { | ||||
| object->attr_map_offset = attr_map_size; | object->attr_map_offset = attr_map_size; | ||||
| attr_map_size += (object_attributes[i].size() + 1) * ATTR_PRIM_TYPES; | attr_map_size += (object_attributes[i].size() + 1) * ATTR_PRIM_TYPES; | ||||
| } | } | ||||
| } | } | ||||
| if (attr_map_size == 0) | if (attr_map_size == 0) | ||||
| return; | return; | ||||
| /* create attribute map */ | /* create attribute map */ | ||||
| uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size); | uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size); | ||||
| memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint)); | memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint)); | ||||
| for (size_t i = 0; i < scene->geometry.size(); i++) { | for (size_t i = 0; i < scene->get_geometry().size(); i++) { | ||||
| Geometry *geom = scene->geometry[i]; | Geometry *geom = scene->get_geometry()[i]; | ||||
| AttributeRequestSet &attributes = geom_attributes[i]; | AttributeRequestSet &attributes = geom_attributes[i]; | ||||
| /* set geometry attributes */ | /* set geometry attributes */ | ||||
| int index = geom->attr_map_offset; | int index = geom->get_attr_map_offset(); | ||||
| foreach (AttributeRequest &req, attributes.requests) { | foreach (const AttributeRequest &req, attributes.get_requests()) { | ||||
| emit_attribute_mapping(attr_map, index, scene, req, geom); | emit_attribute_mapping(attr_map, index, scene, req, geom); | ||||
| index += ATTR_PRIM_TYPES; | index += ATTR_PRIM_TYPES; | ||||
| } | } | ||||
| emit_attribute_map_terminator(attr_map, index, false, 0); | emit_attribute_map_terminator(attr_map, index, false, 0); | ||||
| } | } | ||||
| for (size_t i = 0; i < scene->objects.size(); i++) { | for (size_t i = 0; i < scene->get_objects().size(); i++) { | ||||
| Object *object = scene->objects[i]; | Object *object = scene->get_objects()[i]; | ||||
| AttributeRequestSet &attributes = object_attributes[i]; | AttributeRequestSet &attributes = object_attributes[i]; | ||||
| /* set object attributes */ | /* set object attributes */ | ||||
| if (attributes.size() > 0) { | if (attributes.size() > 0) { | ||||
| int index = object->attr_map_offset; | int index = object->attr_map_offset; | ||||
| foreach (AttributeRequest &req, attributes.requests) { | foreach (const AttributeRequest &req, attributes.get_requests()) { | ||||
| emit_attribute_mapping(attr_map, index, scene, req, object->geometry); | emit_attribute_mapping(attr_map, index, scene, req, object->geometry); | ||||
| index += ATTR_PRIM_TYPES; | index += ATTR_PRIM_TYPES; | ||||
| } | } | ||||
| emit_attribute_map_terminator(attr_map, index, true, object->geometry->attr_map_offset); | emit_attribute_map_terminator( | ||||
| attr_map, index, true, object->geometry->get_attr_map_offset()); | |||||
| } | } | ||||
| } | } | ||||
| /* copy to device */ | /* copy to device */ | ||||
| dscene->attributes_map.copy_to_device(); | dscene->attributes_map.copy_to_device(); | ||||
| } | } | ||||
| static void update_attribute_element_size(Geometry *geom, | static void update_attribute_element_size(Geometry *geom, | ||||
| Attribute *mattr, | Attribute *mattr, | ||||
| AttributePrimitive prim, | AttributePrimitive prim, | ||||
| size_t *attr_float_size, | size_t *attr_float_size, | ||||
| size_t *attr_float2_size, | size_t *attr_float2_size, | ||||
| size_t *attr_float3_size, | size_t *attr_float3_size, | ||||
| size_t *attr_uchar4_size) | size_t *attr_uchar4_size) | ||||
| { | { | ||||
| if (mattr) { | if (mattr) { | ||||
| size_t size = mattr->element_size(geom, prim); | size_t size = mattr->element_size(geom, prim); | ||||
| if (mattr->element == ATTR_ELEMENT_VOXEL) { | if (mattr->get_element() == ATTR_ELEMENT_VOXEL) { | ||||
| /* pass */ | /* pass */ | ||||
| } | } | ||||
| else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) { | else if (mattr->get_element() == ATTR_ELEMENT_CORNER_BYTE) { | ||||
| *attr_uchar4_size += size; | *attr_uchar4_size += size; | ||||
| } | } | ||||
| else if (mattr->type == TypeDesc::TypeFloat) { | else if (mattr->get_type() == TypeDesc::TypeFloat) { | ||||
| *attr_float_size += size; | *attr_float_size += size; | ||||
| } | } | ||||
| else if (mattr->type == TypeFloat2) { | else if (mattr->get_type() == TypeFloat2) { | ||||
| *attr_float2_size += size; | *attr_float2_size += size; | ||||
| } | } | ||||
| else if (mattr->type == TypeDesc::TypeMatrix) { | else if (mattr->get_type() == TypeDesc::TypeMatrix) { | ||||
| *attr_float3_size += size * 4; | *attr_float3_size += size * 4; | ||||
| } | } | ||||
| else { | else { | ||||
| *attr_float3_size += size; | *attr_float3_size += size; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void GeometryManager::update_attribute_element_offset(Geometry *geom, | void GeometryManager::update_attribute_element_offset(Geometry *geom, | ||||
| device_vector<float> &attr_float, | device_vector<float> &attr_float, | ||||
| size_t &attr_float_offset, | size_t &attr_float_offset, | ||||
| device_vector<float2> &attr_float2, | device_vector<float2> &attr_float2, | ||||
| size_t &attr_float2_offset, | size_t &attr_float2_offset, | ||||
| device_vector<float4> &attr_float3, | device_vector<float4> &attr_float3, | ||||
| size_t &attr_float3_offset, | size_t &attr_float3_offset, | ||||
| device_vector<uchar4> &attr_uchar4, | device_vector<uchar4> &attr_uchar4, | ||||
| size_t &attr_uchar4_offset, | size_t &attr_uchar4_offset, | ||||
| Attribute *mattr, | Attribute *mattr, | ||||
| AttributePrimitive prim, | AttributePrimitive prim, | ||||
| TypeDesc &type, | TypeDesc &type, | ||||
| AttributeDescriptor &desc) | AttributeDescriptor &desc) | ||||
| { | { | ||||
| if (mattr) { | if (mattr) { | ||||
| /* store element and type */ | /* store element and type */ | ||||
| desc.element = mattr->element; | desc.element = mattr->get_element(); | ||||
| desc.flags = mattr->flags; | desc.flags = mattr->get_flags(); | ||||
| type = mattr->type; | type = mattr->get_type(); | ||||
| /* store attribute data in arrays */ | /* store attribute data in arrays */ | ||||
| size_t size = mattr->element_size(geom, prim); | size_t size = mattr->element_size(geom, prim); | ||||
| AttributeElement &element = desc.element; | AttributeElement &element = desc.element; | ||||
| int &offset = desc.offset; | int &offset = desc.offset; | ||||
| if (mattr->element == ATTR_ELEMENT_VOXEL) { | if (mattr->get_element() == ATTR_ELEMENT_VOXEL) { | ||||
| /* store slot in offset value */ | /* store slot in offset value */ | ||||
| ImageHandle &handle = mattr->data_voxel(); | ImageHandle &handle = mattr->data_voxel(); | ||||
| offset = handle.svm_slot(); | offset = handle.svm_slot(); | ||||
| } | } | ||||
| else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) { | else if (mattr->get_element() == ATTR_ELEMENT_CORNER_BYTE) { | ||||
| uchar4 *data = mattr->data_uchar4(); | uchar4 *data = mattr->data_uchar4(); | ||||
| offset = attr_uchar4_offset; | offset = attr_uchar4_offset; | ||||
| assert(attr_uchar4.size() >= offset + size); | assert(attr_uchar4.size() >= offset + size); | ||||
| for (size_t k = 0; k < size; k++) { | for (size_t k = 0; k < size; k++) { | ||||
| attr_uchar4[offset + k] = data[k]; | attr_uchar4[offset + k] = data[k]; | ||||
| } | } | ||||
| attr_uchar4_offset += size; | attr_uchar4_offset += size; | ||||
| } | } | ||||
| else if (mattr->type == TypeDesc::TypeFloat) { | else if (mattr->get_type() == TypeDesc::TypeFloat) { | ||||
| float *data = mattr->data_float(); | float *data = mattr->data_float(); | ||||
| offset = attr_float_offset; | offset = attr_float_offset; | ||||
| assert(attr_float.size() >= offset + size); | assert(attr_float.size() >= offset + size); | ||||
| for (size_t k = 0; k < size; k++) { | for (size_t k = 0; k < size; k++) { | ||||
| attr_float[offset + k] = data[k]; | attr_float[offset + k] = data[k]; | ||||
| } | } | ||||
| attr_float_offset += size; | attr_float_offset += size; | ||||
| } | } | ||||
| else if (mattr->type == TypeFloat2) { | else if (mattr->get_type() == TypeFloat2) { | ||||
| float2 *data = mattr->data_float2(); | float2 *data = mattr->data_float2(); | ||||
| offset = attr_float2_offset; | offset = attr_float2_offset; | ||||
| assert(attr_float2.size() >= offset + size); | assert(attr_float2.size() >= offset + size); | ||||
| for (size_t k = 0; k < size; k++) { | for (size_t k = 0; k < size; k++) { | ||||
| attr_float2[offset + k] = data[k]; | attr_float2[offset + k] = data[k]; | ||||
| } | } | ||||
| attr_float2_offset += size; | attr_float2_offset += size; | ||||
| } | } | ||||
| else if (mattr->type == TypeDesc::TypeMatrix) { | else if (mattr->get_type() == TypeDesc::TypeMatrix) { | ||||
| Transform *tfm = mattr->data_transform(); | Transform *tfm = mattr->data_transform(); | ||||
| offset = attr_float3_offset; | offset = attr_float3_offset; | ||||
| assert(attr_float3.size() >= offset + size * 3); | assert(attr_float3.size() >= offset + size * 3); | ||||
| for (size_t k = 0; k < size * 3; k++) { | for (size_t k = 0; k < size * 3; k++) { | ||||
| attr_float3[offset + k] = (&tfm->x)[k]; | attr_float3[offset + k] = (&tfm->x)[k]; | ||||
| } | } | ||||
| attr_float3_offset += size * 3; | attr_float3_offset += size * 3; | ||||
| Show All 33 Lines | if (geom->is_mesh()) { | ||||
| offset -= 3 * mesh->prim_offset; | offset -= 3 * mesh->prim_offset; | ||||
| else | else | ||||
| offset -= mesh->corner_offset; | offset -= mesh->corner_offset; | ||||
| } | } | ||||
| } | } | ||||
| else if (geom->is_hair()) { | else if (geom->is_hair()) { | ||||
| Hair *hair = static_cast<Hair *>(geom); | Hair *hair = static_cast<Hair *>(geom); | ||||
| if (element == ATTR_ELEMENT_CURVE) | if (element == ATTR_ELEMENT_CURVE) | ||||
| offset -= hair->prim_offset; | offset -= hair->get_prim_offset(); | ||||
| else if (element == ATTR_ELEMENT_CURVE_KEY) | else if (element == ATTR_ELEMENT_CURVE_KEY) | ||||
| offset -= hair->curvekey_offset; | offset -= hair->get_curvekey_offset(); | ||||
| else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION) | else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION) | ||||
| offset -= hair->curvekey_offset; | offset -= hair->get_curvekey_offset(); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* attribute not found */ | /* attribute not found */ | ||||
| desc.element = ATTR_ELEMENT_NONE; | desc.element = ATTR_ELEMENT_NONE; | ||||
| desc.offset = 0; | desc.offset = 0; | ||||
| } | } | ||||
| } | } | ||||
| void GeometryManager::device_update_attributes(Device *device, | void GeometryManager::device_update_attributes(Device *device, | ||||
| DeviceScene *dscene, | DeviceScene *dscene, | ||||
| Scene *scene, | Scene *scene, | ||||
| Progress &progress) | Progress &progress) | ||||
| { | { | ||||
| progress.set_status("Updating Mesh", "Computing attributes"); | progress.set_status("Updating Mesh", "Computing attributes"); | ||||
| /* gather per mesh requested attributes. as meshes may have multiple | /* gather per mesh requested attributes. as meshes may have multiple | ||||
| * shaders assigned, this merges the requested attributes that have | * shaders assigned, this merges the requested attributes that have | ||||
| * been set per shader by the shader manager */ | * been set per shader by the shader manager */ | ||||
| vector<AttributeRequestSet> geom_attributes(scene->geometry.size()); | vector<AttributeRequestSet> geom_attributes(scene->get_geometry().size()); | ||||
| for (size_t i = 0; i < scene->geometry.size(); i++) { | for (size_t i = 0; i < scene->get_geometry().size(); i++) { | ||||
| Geometry *geom = scene->geometry[i]; | Geometry *geom = scene->get_geometry()[i]; | ||||
| geom->index = i; | geom->set_index(i); | ||||
| scene->need_global_attributes(geom_attributes[i]); | scene->need_global_attributes(geom_attributes[i]); | ||||
| foreach (Node *node, geom->get_used_shaders()) { | foreach (Node *node, geom->get_used_shaders()) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| geom_attributes[i].add(shader->attributes); | geom_attributes[i].add(shader->get_attributes()); | ||||
| } | } | ||||
| } | } | ||||
| /* convert object attributes to use the same data structures as geometry ones */ | /* convert object attributes to use the same data structures as geometry ones */ | ||||
| vector<AttributeRequestSet> object_attributes(scene->objects.size()); | vector<AttributeRequestSet> object_attributes(scene->get_objects().size()); | ||||
| vector<AttributeSet> object_attribute_values; | vector<AttributeSet> object_attribute_values; | ||||
| object_attribute_values.reserve(scene->objects.size()); | object_attribute_values.reserve(scene->get_objects().size()); | ||||
| for (size_t i = 0; i < scene->objects.size(); i++) { | for (size_t i = 0; i < scene->get_objects().size(); i++) { | ||||
| Object *object = scene->objects[i]; | Object *object = scene->get_objects()[i]; | ||||
| Geometry *geom = object->geometry; | Geometry *geom = object->geometry; | ||||
| size_t geom_idx = geom->index; | size_t geom_idx = geom->get_index(); | ||||
| assert(geom_idx < scene->geometry.size() && scene->geometry[geom_idx] == geom); | assert(geom_idx < scene->get_geometry().size() && scene->get_geometry()[geom_idx] == geom); | ||||
| object_attribute_values.push_back(AttributeSet(geom, ATTR_PRIM_GEOMETRY)); | object_attribute_values.push_back(AttributeSet(geom, ATTR_PRIM_GEOMETRY)); | ||||
| AttributeRequestSet &geom_requests = geom_attributes[geom_idx]; | AttributeRequestSet &geom_requests = geom_attributes[geom_idx]; | ||||
| AttributeRequestSet &attributes = object_attributes[i]; | AttributeRequestSet &attributes = object_attributes[i]; | ||||
| AttributeSet &values = object_attribute_values[i]; | AttributeSet &values = object_attribute_values[i]; | ||||
| for (size_t j = 0; j < object->attributes.size(); j++) { | foreach (const ParamValue ¶m, object->attributes) { | ||||
| ParamValue ¶m = object->attributes[j]; | |||||
| /* add attributes that are requested and not already handled by the mesh */ | /* add attributes that are requested and not already handled by the mesh */ | ||||
| if (geom_requests.find(param.name()) && !geom->attributes.find(param.name())) { | if (geom_requests.find(param.name()) && !geom->get_attributes().find(param.name())) { | ||||
| attributes.add(param.name()); | attributes.add(param.name()); | ||||
| Attribute *attr = values.add(param.name(), param.type(), ATTR_ELEMENT_OBJECT); | Attribute *attr = values.add(param.name(), param.type(), ATTR_ELEMENT_OBJECT); | ||||
| assert(param.datasize() == attr->buffer.size()); | assert(param.datasize() == attr->get_buffer().size()); | ||||
| memcpy(attr->buffer.data(), param.data(), param.datasize()); | memcpy(attr->get_buffer().data(), param.data(), param.datasize()); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* mesh attribute are stored in a single array per data type. here we fill | /* mesh attribute are stored in a single array per data type. here we fill | ||||
| * those arrays, and set the offset and element type to create attribute | * those arrays, and set the offset and element type to create attribute | ||||
| * maps next */ | * maps next */ | ||||
| /* Pre-allocate attributes to avoid arrays re-allocation which would | /* Pre-allocate attributes to avoid arrays re-allocation which would | ||||
| * take 2x of overall attribute memory usage. | * take 2x of overall attribute memory usage. | ||||
| */ | */ | ||||
| size_t attr_float_size = 0; | size_t attr_float_size = 0; | ||||
| size_t attr_float2_size = 0; | size_t attr_float2_size = 0; | ||||
| size_t attr_float3_size = 0; | size_t attr_float3_size = 0; | ||||
| size_t attr_uchar4_size = 0; | size_t attr_uchar4_size = 0; | ||||
| for (size_t i = 0; i < scene->get_geometry().size(); i++) { | |||||
| for (size_t i = 0; i < scene->geometry.size(); i++) { | Geometry *geom = scene->get_geometry()[i]; | ||||
| Geometry *geom = scene->geometry[i]; | |||||
| AttributeRequestSet &attributes = geom_attributes[i]; | AttributeRequestSet &attributes = geom_attributes[i]; | ||||
| foreach (AttributeRequest &req, attributes.requests) { | foreach (const AttributeRequest &req, attributes.get_requests()) { | ||||
| Attribute *attr = geom->attributes.find(req); | Attribute *attr = geom->get_attributes().find(req); | ||||
| update_attribute_element_size(geom, | update_attribute_element_size(geom, | ||||
| attr, | attr, | ||||
| ATTR_PRIM_GEOMETRY, | ATTR_PRIM_GEOMETRY, | ||||
| &attr_float_size, | &attr_float_size, | ||||
| &attr_float2_size, | &attr_float2_size, | ||||
| &attr_float3_size, | &attr_float3_size, | ||||
| &attr_uchar4_size); | &attr_uchar4_size); | ||||
| if (geom->is_mesh()) { | if (geom->is_mesh()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| Attribute *subd_attr = mesh->subd_attributes.find(req); | Attribute *subd_attr = mesh->subd_attributes.find(req); | ||||
| update_attribute_element_size(mesh, | update_attribute_element_size(mesh, | ||||
| subd_attr, | subd_attr, | ||||
| ATTR_PRIM_SUBD, | ATTR_PRIM_SUBD, | ||||
| &attr_float_size, | &attr_float_size, | ||||
| &attr_float2_size, | &attr_float2_size, | ||||
| &attr_float3_size, | &attr_float3_size, | ||||
| &attr_uchar4_size); | &attr_uchar4_size); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| for (size_t i = 0; i < scene->objects.size(); i++) { | for (size_t i = 0; i < scene->get_objects().size(); i++) { | ||||
| Object *object = scene->objects[i]; | Object *object = scene->get_objects()[i]; | ||||
| foreach (Attribute &attr, object_attribute_values[i].attributes) { | foreach (Attribute &attr, object_attribute_values[i].get_attributes()) { | ||||
| update_attribute_element_size(object->geometry, | update_attribute_element_size(object->geometry, | ||||
| &attr, | &attr, | ||||
| ATTR_PRIM_GEOMETRY, | ATTR_PRIM_GEOMETRY, | ||||
| &attr_float_size, | &attr_float_size, | ||||
| &attr_float2_size, | &attr_float2_size, | ||||
| &attr_float3_size, | &attr_float3_size, | ||||
| &attr_uchar4_size); | &attr_uchar4_size); | ||||
| } | } | ||||
| } | } | ||||
| dscene->attributes_float.alloc(attr_float_size); | dscene->attributes_float.alloc(attr_float_size); | ||||
| dscene->attributes_float2.alloc(attr_float2_size); | dscene->attributes_float2.alloc(attr_float2_size); | ||||
| dscene->attributes_float3.alloc(attr_float3_size); | dscene->attributes_float3.alloc(attr_float3_size); | ||||
| dscene->attributes_uchar4.alloc(attr_uchar4_size); | dscene->attributes_uchar4.alloc(attr_uchar4_size); | ||||
| size_t attr_float_offset = 0; | size_t attr_float_offset = 0; | ||||
| size_t attr_float2_offset = 0; | size_t attr_float2_offset = 0; | ||||
| size_t attr_float3_offset = 0; | size_t attr_float3_offset = 0; | ||||
| size_t attr_uchar4_offset = 0; | size_t attr_uchar4_offset = 0; | ||||
| /* Fill in attributes. */ | /* Fill in attributes. */ | ||||
| for (size_t i = 0; i < scene->geometry.size(); i++) { | for (size_t i = 0; i < scene->get_geometry().size(); i++) { | ||||
| Geometry *geom = scene->geometry[i]; | Geometry *geom = scene->get_geometry()[i]; | ||||
| AttributeRequestSet &attributes = geom_attributes[i]; | AttributeRequestSet &attributes = geom_attributes[i]; | ||||
| /* todo: we now store std and name attributes from requests even if | /* todo: we now store std and name attributes from requests even if | ||||
| * they actually refer to the same mesh attributes, optimize */ | * they actually refer to the same mesh attributes, optimize */ | ||||
| foreach (AttributeRequest &req, attributes.requests) { | foreach (AttributeRequest &req, attributes.get_requests()) { | ||||
| Attribute *attr = geom->attributes.find(req); | Attribute *attr = geom->get_attributes().find(req); | ||||
| update_attribute_element_offset(geom, | update_attribute_element_offset(geom, | ||||
| dscene->attributes_float, | dscene->attributes_float, | ||||
| attr_float_offset, | attr_float_offset, | ||||
| dscene->attributes_float2, | dscene->attributes_float2, | ||||
| attr_float2_offset, | attr_float2_offset, | ||||
| dscene->attributes_float3, | dscene->attributes_float3, | ||||
| attr_float3_offset, | attr_float3_offset, | ||||
| dscene->attributes_uchar4, | dscene->attributes_uchar4, | ||||
| attr_uchar4_offset, | attr_uchar4_offset, | ||||
| attr, | attr, | ||||
| ATTR_PRIM_GEOMETRY, | ATTR_PRIM_GEOMETRY, | ||||
| req.type, | req.get_type(), | ||||
| req.desc); | req.get_desc()); | ||||
| if (geom->is_mesh()) { | if (geom->is_mesh()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| Attribute *subd_attr = mesh->subd_attributes.find(req); | Attribute *subd_attr = mesh->subd_attributes.find(req); | ||||
| update_attribute_element_offset(mesh, | update_attribute_element_offset(mesh, | ||||
| dscene->attributes_float, | dscene->attributes_float, | ||||
| attr_float_offset, | attr_float_offset, | ||||
| dscene->attributes_float2, | dscene->attributes_float2, | ||||
| attr_float2_offset, | attr_float2_offset, | ||||
| dscene->attributes_float3, | dscene->attributes_float3, | ||||
| attr_float3_offset, | attr_float3_offset, | ||||
| dscene->attributes_uchar4, | dscene->attributes_uchar4, | ||||
| attr_uchar4_offset, | attr_uchar4_offset, | ||||
| subd_attr, | subd_attr, | ||||
| ATTR_PRIM_SUBD, | ATTR_PRIM_SUBD, | ||||
| req.subd_type, | req.get_subd_type(), | ||||
| req.subd_desc); | req.get_subd_desc()); | ||||
| } | } | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| for (size_t i = 0; i < scene->objects.size(); i++) { | for (size_t i = 0; i < scene->get_objects().size(); i++) { | ||||
| Object *object = scene->objects[i]; | Object *object = scene->get_objects()[i]; | ||||
| AttributeRequestSet &attributes = object_attributes[i]; | AttributeRequestSet &attributes = object_attributes[i]; | ||||
| AttributeSet &values = object_attribute_values[i]; | AttributeSet &values = object_attribute_values[i]; | ||||
| foreach (AttributeRequest &req, attributes.requests) { | foreach (AttributeRequest &req, attributes.get_requests()) { | ||||
| Attribute *attr = values.find(req); | Attribute *attr = values.find(req); | ||||
| update_attribute_element_offset(object->geometry, | update_attribute_element_offset(object->geometry, | ||||
| dscene->attributes_float, | dscene->attributes_float, | ||||
| attr_float_offset, | attr_float_offset, | ||||
| dscene->attributes_float2, | dscene->attributes_float2, | ||||
| attr_float2_offset, | attr_float2_offset, | ||||
| dscene->attributes_float3, | dscene->attributes_float3, | ||||
| attr_float3_offset, | attr_float3_offset, | ||||
| dscene->attributes_uchar4, | dscene->attributes_uchar4, | ||||
| attr_uchar4_offset, | attr_uchar4_offset, | ||||
| attr, | attr, | ||||
| ATTR_PRIM_GEOMETRY, | ATTR_PRIM_GEOMETRY, | ||||
| req.type, | req.get_type(), | ||||
| req.desc); | req.get_desc()); | ||||
| /* object attributes don't care about subdivision */ | /* object attributes don't care about subdivision */ | ||||
| req.subd_type = req.type; | req.get_subd_type() = req.get_type(); | ||||
| req.subd_desc = req.desc; | req.get_subd_desc() = req.get_desc(); | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| /* create attribute lookup maps */ | /* create attribute lookup maps */ | ||||
| if (scene->shader_manager->use_osl()) | if (scene->get_shader_manager()->use_osl()) | ||||
| update_osl_attributes(device, scene, geom_attributes); | update_osl_attributes(device, scene, geom_attributes); | ||||
| update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes); | update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes); | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| return; | return; | ||||
| /* copy to device */ | /* copy to device */ | ||||
| Show All 12 Lines | if (dscene->attributes_uchar4.size()) { | ||||
| dscene->attributes_uchar4.copy_to_device(); | dscene->attributes_uchar4.copy_to_device(); | ||||
| } | } | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| return; | return; | ||||
| /* After mesh attributes and patch tables have been copied to device memory, | /* After mesh attributes and patch tables have been copied to device memory, | ||||
| * we need to update offsets in the objects. */ | * we need to update offsets in the objects. */ | ||||
| scene->object_manager->device_update_mesh_offsets(device, dscene, scene); | scene->get_object_manager()->device_update_mesh_offsets(device, dscene, scene); | ||||
| } | } | ||||
| void GeometryManager::mesh_calc_offset(Scene *scene, BVHLayout bvh_layout) | void GeometryManager::mesh_calc_offset(Scene *scene, BVHLayout bvh_layout) | ||||
| { | { | ||||
| size_t vert_size = 0; | size_t vert_size = 0; | ||||
| size_t tri_size = 0; | size_t tri_size = 0; | ||||
| size_t curve_key_size = 0; | size_t curve_key_size = 0; | ||||
| size_t curve_size = 0; | size_t curve_size = 0; | ||||
| size_t patch_size = 0; | size_t patch_size = 0; | ||||
| size_t face_size = 0; | size_t face_size = 0; | ||||
| size_t corner_size = 0; | size_t corner_size = 0; | ||||
| size_t optix_prim_size = 0; | size_t optix_prim_size = 0; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->optix_prim_offset != optix_prim_size) { | if (geom->get_optix_prim_offset() != optix_prim_size) { | ||||
| /* Need to rebuild BVH in OptiX, since refit only allows modified mesh data there */ | /* Need to rebuild BVH in OptiX, since refit only allows modified mesh data there */ | ||||
| const bool has_optix_bvh = bvh_layout == BVH_LAYOUT_OPTIX || | const bool has_optix_bvh = bvh_layout == BVH_LAYOUT_OPTIX || | ||||
| bvh_layout == BVH_LAYOUT_MULTI_OPTIX || | bvh_layout == BVH_LAYOUT_MULTI_OPTIX || | ||||
| bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE; | bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE; | ||||
| geom->tag_bvh_update(has_optix_bvh); | geom->tag_bvh_update(has_optix_bvh); | ||||
| } | } | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| mesh->vert_offset = vert_size; | mesh->vert_offset = vert_size; | ||||
| mesh->prim_offset = tri_size; | mesh->prim_offset = tri_size; | ||||
| mesh->patch_offset = patch_size; | mesh->patch_offset = patch_size; | ||||
| mesh->face_offset = face_size; | mesh->face_offset = face_size; | ||||
| mesh->corner_offset = corner_size; | mesh->corner_offset = corner_size; | ||||
| Show All 16 Lines | if (geom->is_mesh() || geom->is_volume()) { | ||||
| corner_size += mesh->subd_face_corners.size(); | corner_size += mesh->subd_face_corners.size(); | ||||
| mesh->optix_prim_offset = optix_prim_size; | mesh->optix_prim_offset = optix_prim_size; | ||||
| optix_prim_size += mesh->num_triangles(); | optix_prim_size += mesh->num_triangles(); | ||||
| } | } | ||||
| else if (geom->is_hair()) { | else if (geom->is_hair()) { | ||||
| Hair *hair = static_cast<Hair *>(geom); | Hair *hair = static_cast<Hair *>(geom); | ||||
| hair->curvekey_offset = curve_key_size; | hair->set_curvekey_offset(curve_key_size); | ||||
| hair->prim_offset = curve_size; | hair->set_prim_offset(curve_size); | ||||
| curve_key_size += hair->get_curve_keys().size(); | curve_key_size += hair->get_curve_keys().size(); | ||||
| curve_size += hair->num_curves(); | curve_size += hair->num_curves(); | ||||
| hair->optix_prim_offset = optix_prim_size; | hair->set_optix_prim_offset(optix_prim_size); | ||||
| optix_prim_size += hair->num_segments(); | optix_prim_size += hair->num_segments(); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void GeometryManager::device_update_mesh( | void GeometryManager::device_update_mesh( | ||||
| Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress) | Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress) | ||||
| { | { | ||||
| /* Count. */ | /* Count. */ | ||||
| size_t vert_size = 0; | size_t vert_size = 0; | ||||
| size_t tri_size = 0; | size_t tri_size = 0; | ||||
| size_t curve_key_size = 0; | size_t curve_key_size = 0; | ||||
| size_t curve_size = 0; | size_t curve_size = 0; | ||||
| size_t patch_size = 0; | size_t patch_size = 0; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| vert_size += mesh->verts.size(); | vert_size += mesh->verts.size(); | ||||
| tri_size += mesh->num_triangles(); | tri_size += mesh->num_triangles(); | ||||
| if (mesh->get_num_subd_faces()) { | if (mesh->get_num_subd_faces()) { | ||||
| Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1); | Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1); | ||||
| patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; | patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; | ||||
| Show All 16 Lines | void GeometryManager::device_update_mesh( | ||||
| /* Create mapping from triangle to primitive triangle array. */ | /* Create mapping from triangle to primitive triangle array. */ | ||||
| vector<uint> tri_prim_index(tri_size); | vector<uint> tri_prim_index(tri_size); | ||||
| if (for_displacement) { | if (for_displacement) { | ||||
| /* For displacement kernels we do some trickery to make them believe | /* For displacement kernels we do some trickery to make them believe | ||||
| * we've got all required data ready. However, that data is different | * we've got all required data ready. However, that data is different | ||||
| * from final render kernels since we don't have BVH yet, so can't | * from final render kernels since we don't have BVH yet, so can't | ||||
| * really use same semantic of arrays. | * really use same semantic of arrays. | ||||
| */ | */ | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| for (size_t i = 0; i < mesh->num_triangles(); ++i) { | for (size_t i = 0; i < mesh->num_triangles(); ++i) { | ||||
| tri_prim_index[i + mesh->prim_offset] = 3 * (i + mesh->prim_offset); | tri_prim_index[i + mesh->prim_offset] = 3 * (i + mesh->prim_offset); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 10 Lines | if (tri_size != 0) { | ||||
| progress.set_status("Updating Mesh", "Computing normals"); | progress.set_status("Updating Mesh", "Computing normals"); | ||||
| uint *tri_shader = dscene->tri_shader.alloc(tri_size); | uint *tri_shader = dscene->tri_shader.alloc(tri_size); | ||||
| float4 *vnormal = dscene->tri_vnormal.alloc(vert_size); | float4 *vnormal = dscene->tri_vnormal.alloc(vert_size); | ||||
| uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size); | uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size); | ||||
| uint *tri_patch = dscene->tri_patch.alloc(tri_size); | uint *tri_patch = dscene->tri_patch.alloc(tri_size); | ||||
| float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); | float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]); | mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]); | ||||
| mesh->pack_normals(&vnormal[mesh->vert_offset]); | mesh->pack_normals(&vnormal[mesh->vert_offset]); | ||||
| mesh->pack_verts(tri_prim_index, | mesh->pack_verts(tri_prim_index, | ||||
| &tri_vindex[mesh->prim_offset], | &tri_vindex[mesh->prim_offset], | ||||
| &tri_patch[mesh->prim_offset], | &tri_patch[mesh->prim_offset], | ||||
| &tri_patch_uv[mesh->vert_offset], | &tri_patch_uv[mesh->vert_offset], | ||||
| mesh->vert_offset, | mesh->vert_offset, | ||||
| Show All 14 Lines | void GeometryManager::device_update_mesh( | ||||
| } | } | ||||
| if (curve_size != 0) { | if (curve_size != 0) { | ||||
| progress.set_status("Updating Mesh", "Copying Strands to device"); | progress.set_status("Updating Mesh", "Copying Strands to device"); | ||||
| float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size); | float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size); | ||||
| float4 *curves = dscene->curves.alloc(curve_size); | float4 *curves = dscene->curves.alloc(curve_size); | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->is_hair()) { | if (geom->is_hair()) { | ||||
| Hair *hair = static_cast<Hair *>(geom); | Hair *hair = static_cast<Hair *>(geom); | ||||
| hair->pack_curves(scene, | hair->pack_curves(scene, | ||||
| &curve_keys[hair->curvekey_offset], | &curve_keys[hair->get_curvekey_offset()], | ||||
| &curves[hair->prim_offset], | &curves[hair->get_prim_offset()], | ||||
| hair->curvekey_offset); | hair->get_curvekey_offset()); | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| dscene->curve_keys.copy_to_device(); | dscene->curve_keys.copy_to_device(); | ||||
| dscene->curves.copy_to_device(); | dscene->curves.copy_to_device(); | ||||
| } | } | ||||
| if (patch_size != 0) { | if (patch_size != 0) { | ||||
| progress.set_status("Updating Mesh", "Copying Patches to device"); | progress.set_status("Updating Mesh", "Copying Patches to device"); | ||||
| uint *patch_data = dscene->patches.alloc(patch_size); | uint *patch_data = dscene->patches.alloc(patch_size); | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->is_mesh()) { | if (geom->is_mesh()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| mesh->pack_patches(&patch_data[mesh->patch_offset], | mesh->pack_patches(&patch_data[mesh->patch_offset], | ||||
| mesh->vert_offset, | mesh->vert_offset, | ||||
| mesh->face_offset, | mesh->face_offset, | ||||
| mesh->corner_offset); | mesh->corner_offset); | ||||
| if (mesh->patch_table) { | if (mesh->patch_table) { | ||||
| mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], | mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], | ||||
| mesh->patch_table_offset); | mesh->patch_table_offset); | ||||
| } | } | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| dscene->patches.copy_to_device(); | dscene->patches.copy_to_device(); | ||||
| } | } | ||||
| if (for_displacement) { | if (for_displacement) { | ||||
| float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3); | float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3); | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| for (size_t i = 0; i < mesh->num_triangles(); ++i) { | for (size_t i = 0; i < mesh->num_triangles(); ++i) { | ||||
| Mesh::Triangle t = mesh->get_triangle(i); | Mesh::Triangle t = mesh->get_triangle(i); | ||||
| size_t offset = 3 * (i + mesh->prim_offset); | size_t offset = 3 * (i + mesh->prim_offset); | ||||
| prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]); | prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]); | ||||
| prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]); | prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]); | ||||
| prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]); | prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| dscene->prim_tri_verts.copy_to_device(); | dscene->prim_tri_verts.copy_to_device(); | ||||
| } | } | ||||
| } | } | ||||
| void GeometryManager::device_update_bvh(Device *device, | void GeometryManager::device_update_bvh(Device *device, | ||||
| DeviceScene *dscene, | DeviceScene *dscene, | ||||
| Scene *scene, | Scene *scene, | ||||
| Progress &progress) | Progress &progress) | ||||
| { | { | ||||
| /* bvh build */ | /* bvh build */ | ||||
| progress.set_status("Updating Scene BVH", "Building"); | progress.set_status("Updating Scene BVH", "Building"); | ||||
| BVHParams bparams; | BVHParams bparams; | ||||
| bparams.top_level = true; | bparams.top_level = true; | ||||
| bparams.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout, | bparams.bvh_layout = BVHParams::best_bvh_layout(scene->get_params().bvh_layout, | ||||
| device->get_bvh_layout_mask()); | device->get_bvh_layout_mask()); | ||||
| bparams.use_spatial_split = scene->params.use_bvh_spatial_split; | bparams.use_spatial_split = scene->get_params().use_bvh_spatial_split; | ||||
| bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && | bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && | ||||
| scene->params.use_bvh_unaligned_nodes; | scene->get_params().use_bvh_unaligned_nodes; | ||||
| bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps; | bparams.num_motion_triangle_steps = scene->get_params().num_bvh_time_steps; | ||||
| bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps; | bparams.num_motion_curve_steps = scene->get_params().num_bvh_time_steps; | ||||
| bparams.bvh_type = scene->params.bvh_type; | bparams.bvh_type = scene->get_params().bvh_type; | ||||
| bparams.curve_subdivisions = scene->params.curve_subdivisions(); | bparams.curve_subdivisions = scene->get_params().curve_subdivisions(); | ||||
| VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; | VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; | ||||
| delete scene->bvh; | delete scene->get_bvh(); | ||||
| BVH *bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device); | BVH *bvh = BVH::create(bparams, scene->get_geometry(), scene->get_objects(), device); | ||||
| scene->set_bvh(bvh); | |||||
| device->build_bvh(bvh, progress, false); | device->build_bvh(bvh, progress, false); | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| PackedBVH pack; | PackedBVH pack; | ||||
| if (bparams.bvh_layout == BVH_LAYOUT_BVH2) { | if (bparams.bvh_layout == BVH_LAYOUT_BVH2) { | ||||
| pack = std::move(static_cast<BVH2 *>(bvh)->pack); | pack = std::move(static_cast<BVH2 *>(bvh)->pack); | ||||
| } | } | ||||
| else { | else { | ||||
| progress.set_status("Updating Scene BVH", "Packing BVH primitives"); | progress.set_status("Updating Scene BVH", "Packing BVH primitives"); | ||||
| size_t num_prims = 0; | size_t num_prims = 0; | ||||
| size_t num_tri_verts = 0; | size_t num_tri_verts = 0; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { | if (geom->is_mesh() || geom->is_volume()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| num_prims += mesh->num_triangles(); | num_prims += mesh->num_triangles(); | ||||
| num_tri_verts += 3 * mesh->num_triangles(); | num_tri_verts += 3 * mesh->num_triangles(); | ||||
| } | } | ||||
| else if (geom->is_hair()) { | else if (geom->is_hair()) { | ||||
| Hair *hair = static_cast<Hair *>(geom); | Hair *hair = static_cast<Hair *>(geom); | ||||
| num_prims += hair->num_segments(); | num_prims += hair->num_segments(); | ||||
| } | } | ||||
| } | } | ||||
| pack.root_index = -1; | pack.root_index = -1; | ||||
| pack.prim_tri_index.reserve(num_prims); | pack.prim_tri_index.reserve(num_prims); | ||||
| pack.prim_tri_verts.reserve(num_tri_verts); | pack.prim_tri_verts.reserve(num_tri_verts); | ||||
| pack.prim_type.reserve(num_prims); | pack.prim_type.reserve(num_prims); | ||||
| pack.prim_index.reserve(num_prims); | pack.prim_index.reserve(num_prims); | ||||
| pack.prim_object.reserve(num_prims); | pack.prim_object.reserve(num_prims); | ||||
| pack.prim_visibility.reserve(num_prims); | pack.prim_visibility.reserve(num_prims); | ||||
| // Merge visibility flags of all objects and find object index for non-instanced geometry | // Merge visibility flags of all objects and find object index for non-instanced geometry | ||||
| unordered_map<const Geometry *, pair<int, uint>> geometry_to_object_info; | unordered_map<const Geometry *, pair<int, uint>> geometry_to_object_info; | ||||
| geometry_to_object_info.reserve(scene->geometry.size()); | geometry_to_object_info.reserve(scene->get_geometry().size()); | ||||
| foreach (Object *ob, scene->objects) { | foreach (Object *ob, scene->get_objects()) { | ||||
| const Geometry *const geom = ob->get_geometry(); | const Geometry *const geom = ob->get_geometry(); | ||||
| pair<int, uint> &info = geometry_to_object_info[geom]; | pair<int, uint> &info = geometry_to_object_info[geom]; | ||||
| info.second |= ob->visibility_for_tracing(); | info.second |= ob->visibility_for_tracing(); | ||||
| if (!geom->is_instanced()) { | if (!geom->is_instanced()) { | ||||
| info.first = ob->get_device_index(); | info.first = ob->get_device_index(); | ||||
| } | } | ||||
| } | } | ||||
| // Iterate over scene mesh list instead of objects, since 'optix_prim_offset' was calculated | // Iterate over scene mesh list instead of objects, since 'optix_prim_offset' was calculated | ||||
| // based on that list, which may be ordered differently from the object list. | // based on that list, which may be ordered differently from the object list. | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| const pair<int, uint> &info = geometry_to_object_info[geom]; | const pair<int, uint> &info = geometry_to_object_info[geom]; | ||||
| geom->pack_primitives(pack, info.first, info.second); | geom->pack_primitives(pack, info.first, info.second); | ||||
| } | } | ||||
| } | } | ||||
| /* copy to device */ | /* copy to device */ | ||||
| progress.set_status("Updating Scene BVH", "Copying BVH to device"); | progress.set_status("Updating Scene BVH", "Copying BVH to device"); | ||||
| Show All 35 Lines | void GeometryManager::device_update_bvh(Device *device, | ||||
| } | } | ||||
| if (pack.prim_time.size()) { | if (pack.prim_time.size()) { | ||||
| dscene->prim_time.steal_data(pack.prim_time); | dscene->prim_time.steal_data(pack.prim_time); | ||||
| dscene->prim_time.copy_to_device(); | dscene->prim_time.copy_to_device(); | ||||
| } | } | ||||
| dscene->data.bvh.root = pack.root_index; | dscene->data.bvh.root = pack.root_index; | ||||
| dscene->data.bvh.bvh_layout = bparams.bvh_layout; | dscene->data.bvh.bvh_layout = bparams.bvh_layout; | ||||
| dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0); | dscene->data.bvh.use_bvh_steps = (scene->get_params().num_bvh_time_steps != 0); | ||||
| dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions(); | dscene->data.bvh.curve_subdivisions = scene->get_params().curve_subdivisions(); | ||||
| /* The scene handle is set in 'CPUDevice::const_copy_to' and 'OptiXDevice::const_copy_to' */ | /* The scene handle is set in 'CPUDevice::const_copy_to' and 'OptiXDevice::const_copy_to' */ | ||||
| dscene->data.bvh.scene = NULL; | dscene->data.bvh.scene = NULL; | ||||
| } | } | ||||
| void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress) | void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress) | ||||
| { | { | ||||
| if (!need_update && !need_flags_update) { | if (!need_update && !need_flags_update) { | ||||
| return; | return; | ||||
| } | } | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry({"device_update_preprocess", time}); | scene->get_update_stats()->geometry.times.add_entry({"device_update_preprocess", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| progress.set_status("Updating Meshes Flags"); | progress.set_status("Updating Meshes Flags"); | ||||
| /* Update flags. */ | /* Update flags. */ | ||||
| bool volume_images_updated = false; | bool volume_images_updated = false; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| geom->has_volume = false; | geom->set_has_volume(false); | ||||
| foreach (Node *node, geom->get_used_shaders()) { | foreach (Node *node, geom->get_used_shaders()) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| if (shader->has_volume) { | if (shader->get_has_volume()) { | ||||
| geom->has_volume = true; | geom->set_has_volume(true); | ||||
| } | } | ||||
| if (shader->has_surface_bssrdf) { | if (shader->get_has_surface_bssrdf()) { | ||||
| geom->has_surface_bssrdf = true; | geom->set_has_surface_bssrdf(true); | ||||
| } | } | ||||
| } | } | ||||
| /* Re-create volume mesh if we will rebuild or refit the BVH. Note we | /* Re-create volume mesh if we will rebuild or refit the BVH. Note we | ||||
| * should only do it in that case, otherwise the BVH and mesh can go | * should only do it in that case, otherwise the BVH and mesh can go | ||||
| * out of sync. */ | * out of sync. */ | ||||
| if (geom->is_modified() && geom->geometry_type == Geometry::VOLUME) { | if (geom->is_modified() && geom->is_volume()) { | ||||
| /* Create volume meshes if there is voxel data. */ | /* Create volume meshes if there is voxel data. */ | ||||
| if (!volume_images_updated) { | if (!volume_images_updated) { | ||||
| progress.set_status("Updating Meshes Volume Bounds"); | progress.set_status("Updating Meshes Volume Bounds"); | ||||
| device_update_volume_images(device, scene, progress); | device_update_volume_images(device, scene, progress); | ||||
| volume_images_updated = true; | volume_images_updated = true; | ||||
| } | } | ||||
| Volume *volume = static_cast<Volume *>(geom); | Volume *volume = static_cast<Volume *>(geom); | ||||
| create_volume_mesh(volume, progress); | create_volume_mesh(volume, progress); | ||||
| } | } | ||||
| if (geom->is_hair()) { | if (geom->is_hair()) { | ||||
| /* Set curve shape, still a global scene setting for now. */ | /* Set curve shape, still a global scene setting for now. */ | ||||
| Hair *hair = static_cast<Hair *>(geom); | Hair *hair = static_cast<Hair *>(geom); | ||||
| hair->curve_shape = scene->params.hair_shape; | hair->set_curve_shape(scene->get_params().hair_shape); | ||||
| } | } | ||||
| } | } | ||||
| need_flags_update = false; | need_flags_update = false; | ||||
| } | } | ||||
| void GeometryManager::device_update_displacement_images(Device *device, | void GeometryManager::device_update_displacement_images(Device *device, | ||||
| Scene *scene, | Scene *scene, | ||||
| Progress &progress) | Progress &progress) | ||||
| { | { | ||||
| progress.set_status("Updating Displacement Images"); | progress.set_status("Updating Displacement Images"); | ||||
| TaskPool pool; | TaskPool pool; | ||||
| ImageManager *image_manager = scene->image_manager; | ImageManager *image_manager = scene->get_image_manager(); | ||||
| set<int> bump_images; | set<int> bump_images; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->is_modified()) { | if (geom->is_modified()) { | ||||
| foreach (Node *node, geom->get_used_shaders()) { | foreach (Node *node, geom->get_used_shaders()) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) { | if (!shader->get_has_displacement() || | ||||
| shader->get_displacement_method() == DISPLACE_BUMP) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| foreach (ShaderNode *node, shader->graph->nodes) { | foreach (ShaderNode *node, shader->get_graph()->get_nodes()) { | ||||
| if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) { | if (node->get_special_type() != SHADER_SPECIAL_TYPE_IMAGE_SLOT) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node); | ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node); | ||||
| for (int i = 0; i < image_node->handle.num_tiles(); i++) { | for (int i = 0; i < image_node->handle.num_tiles(); i++) { | ||||
| const int slot = image_node->handle.svm_slot(i); | const int slot = image_node->handle.svm_slot(i); | ||||
| if (slot != -1) { | if (slot != -1) { | ||||
| bump_images.insert(slot); | bump_images.insert(slot); | ||||
| Show All 9 Lines | void GeometryManager::device_update_displacement_images(Device *device, | ||||
| } | } | ||||
| pool.wait_work(); | pool.wait_work(); | ||||
| } | } | ||||
| void GeometryManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress) | void GeometryManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress) | ||||
| { | { | ||||
| progress.set_status("Updating Volume Images"); | progress.set_status("Updating Volume Images"); | ||||
| TaskPool pool; | TaskPool pool; | ||||
| ImageManager *image_manager = scene->image_manager; | ImageManager *image_manager = scene->get_image_manager(); | ||||
| set<int> volume_images; | set<int> volume_images; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (!geom->is_modified()) { | if (!geom->is_modified()) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| foreach (Attribute &attr, geom->attributes.attributes) { | foreach (Attribute &attr, geom->get_attributes().get_attributes()) { | ||||
| if (attr.element != ATTR_ELEMENT_VOXEL) { | if (attr.get_element() != ATTR_ELEMENT_VOXEL) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| ImageHandle &handle = attr.data_voxel(); | ImageHandle &handle = attr.data_voxel(); | ||||
| /* We can build directly from OpenVDB data structures, no need to | /* We can build directly from OpenVDB data structures, no need to | ||||
| * load such images early. */ | * load such images early. */ | ||||
| if (!handle.vdb_loader()) { | if (!handle.vdb_loader()) { | ||||
| const int slot = handle.svm_slot(); | const int slot = handle.svm_slot(); | ||||
| Show All 14 Lines | |||||
| void GeometryManager::device_update(Device *device, | void GeometryManager::device_update(Device *device, | ||||
| DeviceScene *dscene, | DeviceScene *dscene, | ||||
| Scene *scene, | Scene *scene, | ||||
| Progress &progress) | Progress &progress) | ||||
| { | { | ||||
| if (!need_update) | if (!need_update) | ||||
| return; | return; | ||||
| VLOG(1) << "Total " << scene->geometry.size() << " meshes."; | VLOG(1) << "Total " << scene->get_geometry().size() << " meshes."; | ||||
| bool true_displacement_used = false; | bool true_displacement_used = false; | ||||
| size_t total_tess_needed = 0; | size_t total_tess_needed = 0; | ||||
| { | { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry({"device_update (normals)", time}); | scene->get_update_stats()->geometry.times.add_entry({"device_update (normals)", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| foreach (Node *node, geom->get_used_shaders()) { | foreach (Node *node, geom->get_used_shaders()) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| if (shader->need_update_geometry) | if (shader->get_need_update_geometry()) | ||||
| geom->tag_modified(); | geom->tag_modified(); | ||||
| } | } | ||||
| if (geom->is_modified() && | if (geom->is_modified() && (geom->is_mesh() || geom->is_volume())) { | ||||
| (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) { | |||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| /* Update normals. */ | /* Update normals. */ | ||||
| mesh->add_face_normals(); | mesh->add_face_normals(); | ||||
| mesh->add_vertex_normals(); | mesh->add_vertex_normals(); | ||||
| if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) { | if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) { | ||||
| mesh->add_undisplaced(); | mesh->add_undisplaced(); | ||||
| Show All 18 Lines | void GeometryManager::device_update(Device *device, | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* Tessellate meshes that are using subdivision */ | /* Tessellate meshes that are using subdivision */ | ||||
| if (total_tess_needed) { | if (total_tess_needed) { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry( | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (adaptive subdivision)", time}); | {"device_update (adaptive subdivision)", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| Camera *dicing_camera = scene->dicing_camera; | Camera *dicing_camera = scene->get_dicing_camera(); | ||||
| dicing_camera->set_screen_size_and_resolution( | dicing_camera->set_screen_size_and_resolution( | ||||
| dicing_camera->get_full_width(), dicing_camera->get_full_height(), 1); | dicing_camera->get_full_width(), dicing_camera->get_full_height(), 1); | ||||
| dicing_camera->update(scene); | dicing_camera->update(scene); | ||||
| size_t i = 0; | size_t i = 0; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (!(geom->is_modified() && geom->is_mesh())) { | if (!(geom->is_modified() && geom->is_mesh())) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| if (mesh->need_tesselation()) { | if (mesh->need_tesselation()) { | ||||
| string msg = "Tessellating "; | string msg = "Tessellating "; | ||||
| if (mesh->name == "") | if (mesh->name == "") | ||||
| Show All 20 Lines | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| /* Update images needed for true displacement. */ | /* Update images needed for true displacement. */ | ||||
| bool old_need_object_flags_update = false; | bool old_need_object_flags_update = false; | ||||
| if (true_displacement_used) { | if (true_displacement_used) { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry( | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (displacement: load images)", time}); | {"device_update (displacement: load images)", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| device_update_displacement_images(device, scene, progress); | device_update_displacement_images(device, scene, progress); | ||||
| old_need_object_flags_update = scene->object_manager->need_flags_update; | old_need_object_flags_update = scene->get_object_manager()->need_flags_update; | ||||
| scene->object_manager->device_update_flags(device, dscene, scene, progress, false); | scene->get_object_manager()->device_update_flags(device, dscene, scene, progress, false); | ||||
| } | } | ||||
| /* Device update. */ | /* Device update. */ | ||||
| device_free(device, dscene); | device_free(device, dscene); | ||||
| const BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout, | const BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->get_params().bvh_layout, | ||||
| device->get_bvh_layout_mask()); | device->get_bvh_layout_mask()); | ||||
| mesh_calc_offset(scene, bvh_layout); | mesh_calc_offset(scene, bvh_layout); | ||||
| if (true_displacement_used) { | if (true_displacement_used) { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry( | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (displacement: copy meshes to device)", time}); | {"device_update (displacement: copy meshes to device)", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| device_update_mesh(device, dscene, scene, true, progress); | device_update_mesh(device, dscene, scene, true, progress); | ||||
| } | } | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| { | { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry({"device_update (attributes)", time}); | scene->get_update_stats()->geometry.times.add_entry({"device_update (attributes)", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| device_update_attributes(device, dscene, scene, progress); | device_update_attributes(device, dscene, scene, progress); | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| /* Update displacement. */ | /* Update displacement. */ | ||||
| bool displacement_done = false; | bool displacement_done = false; | ||||
| size_t num_bvh = 0; | size_t num_bvh = 0; | ||||
| { | { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry({"device_update (displacement)", time}); | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (displacement)", time}); | |||||
| } | } | ||||
| }); | }); | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->is_modified()) { | if (geom->is_modified()) { | ||||
| if (geom->is_mesh()) { | if (geom->is_mesh()) { | ||||
| Mesh *mesh = static_cast<Mesh *>(geom); | Mesh *mesh = static_cast<Mesh *>(geom); | ||||
| if (displace(device, dscene, scene, mesh, progress)) { | if (displace(device, dscene, scene, mesh, progress)) { | ||||
| displacement_done = true; | displacement_done = true; | ||||
| } | } | ||||
| } | } | ||||
| Show All 10 Lines | void GeometryManager::device_update(Device *device, | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* Device re-update after displacement. */ | /* Device re-update after displacement. */ | ||||
| if (displacement_done) { | if (displacement_done) { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry( | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (displacement: attributes)", time}); | {"device_update (displacement: attributes)", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| device_free(device, dscene); | device_free(device, dscene); | ||||
| device_update_attributes(device, dscene, scene, progress); | device_update_attributes(device, dscene, scene, progress); | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| { | { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry({"device_update (build object BVHs)", time}); | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (build object BVHs)", time}); | |||||
| } | } | ||||
| }); | }); | ||||
| TaskPool pool; | TaskPool pool; | ||||
| size_t i = 0; | size_t i = 0; | ||||
| foreach (Geometry *geom, scene->geometry) { | foreach (Geometry *geom, scene->get_geometry()) { | ||||
| if (geom->is_modified()) { | if (geom->is_modified()) { | ||||
| pool.push(function_bind( | pool.push(function_bind(&Geometry::compute_bvh, | ||||
| &Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh)); | geom, | ||||
| device, | |||||
| dscene, | |||||
| &scene->get_params(), | |||||
| &progress, | |||||
| i, | |||||
| num_bvh)); | |||||
| if (geom->need_build_bvh(bvh_layout)) { | if (geom->need_build_bvh(bvh_layout)) { | ||||
| i++; | i++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| TaskPool::Summary summary; | TaskPool::Summary summary; | ||||
| pool.wait_work(&summary); | pool.wait_work(&summary); | ||||
| VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report(); | VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report(); | ||||
| } | } | ||||
| foreach (Shader *shader, scene->shaders) { | foreach (Shader *shader, scene->get_shaders()) { | ||||
| shader->need_update_geometry = false; | shader->set_need_update_geometry(false); | ||||
| } | } | ||||
| Scene::MotionType need_motion = scene->need_motion(); | Scene::MotionType need_motion = scene->need_motion(); | ||||
| bool motion_blur = need_motion == Scene::MOTION_BLUR; | bool motion_blur = need_motion == Scene::MOTION_BLUR; | ||||
| /* Update objects. */ | /* Update objects. */ | ||||
| { | { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry({"device_update (compute bounds)", time}); | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (compute bounds)", time}); | |||||
| } | } | ||||
| }); | }); | ||||
| vector<Object *> volume_objects; | vector<Object *> volume_objects; | ||||
| foreach (Object *object, scene->objects) { | foreach (Object *object, scene->get_objects()) { | ||||
| object->compute_bounds(motion_blur); | object->compute_bounds(motion_blur); | ||||
| } | } | ||||
| } | } | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| { | { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry({"device_update (build scene BVH)", time}); | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (build scene BVH)", time}); | |||||
| } | } | ||||
| }); | }); | ||||
| device_update_bvh(device, dscene, scene, progress); | device_update_bvh(device, dscene, scene, progress); | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| { | { | ||||
| scoped_callback_timer timer([scene](double time) { | scoped_callback_timer timer([scene](double time) { | ||||
| if (scene->update_stats) { | if (scene->get_update_stats()) { | ||||
| scene->update_stats->geometry.times.add_entry( | scene->get_update_stats()->geometry.times.add_entry( | ||||
| {"device_update (copy meshes to device)", time}); | {"device_update (copy meshes to device)", time}); | ||||
| } | } | ||||
| }); | }); | ||||
| device_update_mesh(device, dscene, scene, false, progress); | device_update_mesh(device, dscene, scene, false, progress); | ||||
| if (progress.get_cancel()) { | if (progress.get_cancel()) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| need_update = false; | need_update = false; | ||||
| if (true_displacement_used) { | if (true_displacement_used) { | ||||
| /* Re-tag flags for update, so they're re-evaluated | /* Re-tag flags for update, so they're re-evaluated | ||||
| * for meshes with correct bounding boxes. | * for meshes with correct bounding boxes. | ||||
| * | * | ||||
| * This wouldn't cause wrong results, just true | * This wouldn't cause wrong results, just true | ||||
| * displacement might be less optimal ot calculate. | * displacement might be less optimal ot calculate. | ||||
| */ | */ | ||||
| scene->object_manager->need_flags_update = old_need_object_flags_update; | scene->get_object_manager()->need_flags_update = old_need_object_flags_update; | ||||
| } | } | ||||
| } | } | ||||
| void GeometryManager::device_free(Device *device, DeviceScene *dscene) | void GeometryManager::device_free(Device *device, DeviceScene *dscene) | ||||
| { | { | ||||
| dscene->bvh_nodes.free(); | dscene->bvh_nodes.free(); | ||||
| dscene->bvh_leaf_nodes.free(); | dscene->bvh_leaf_nodes.free(); | ||||
| dscene->object_node.free(); | dscene->object_node.free(); | ||||
| Show All 32 Lines | |||||
| #else | #else | ||||
| (void)device; | (void)device; | ||||
| #endif | #endif | ||||
| } | } | ||||
| void GeometryManager::tag_update(Scene *scene) | void GeometryManager::tag_update(Scene *scene) | ||||
| { | { | ||||
| need_update = true; | need_update = true; | ||||
| scene->object_manager->need_update = true; | scene->get_object_manager()->need_update = true; | ||||
| } | } | ||||
| void GeometryManager::collect_statistics(const Scene *scene, RenderStats *stats) | void GeometryManager::collect_statistics(const Scene *scene, RenderStats *stats) | ||||
| { | { | ||||
| foreach (Geometry *geometry, scene->geometry) { | foreach (Geometry *geometry, scene->get_geometry()) { | ||||
| stats->mesh.geometry.add_entry( | stats->mesh.geometry.add_entry( | ||||
| NamedSizeEntry(string(geometry->name.c_str()), geometry->get_total_size_in_bytes())); | NamedSizeEntry(string(geometry->get_name().c_str()), geometry->get_total_size_in_bytes())); | ||||
| } | } | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||