diff options
Diffstat (limited to 'intern/cycles/render/mesh.cpp')
-rw-r--r-- | intern/cycles/render/mesh.cpp | 306 |
1 files changed, 262 insertions, 44 deletions
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 5602609c030..57f194651f8 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -11,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ #include "bvh.h" @@ -20,9 +20,11 @@ #include "camera.h" #include "curves.h" #include "device.h" +#include "graph.h" #include "shader.h" #include "light.h" #include "mesh.h" +#include "nodes.h" #include "object.h" #include "scene.h" @@ -30,6 +32,7 @@ #include "util_cache.h" #include "util_foreach.h" +#include "util_logging.h" #include "util_progress.h" #include "util_set.h" @@ -93,6 +96,8 @@ Mesh::Mesh() attributes.triangle_mesh = this; curve_attributes.curve_mesh = this; + + has_volume = false; } Mesh::~Mesh() @@ -132,7 +137,7 @@ void Mesh::clear() transform_applied = false; transform_negative_scaled = false; transform_normal = transform_identity(); - geometry_synced = false; + geometry_flags = GEOMETRY_NONE; } int Mesh::split_vertex(int vertex) @@ -207,11 +212,11 @@ void Mesh::compute_bounds() bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w); Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (use_motion_blur && attr) { + if(use_motion_blur && attr) { size_t steps_size = verts.size() * (motion_steps - 1); float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow(vert_steps[i]); } @@ -220,7 +225,7 @@ void Mesh::compute_bounds() size_t steps_size = curve_keys.size() * (motion_steps - 1); float3 *key_steps = curve_attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow(key_steps[i]); } @@ -234,19 +239,19 @@ void Mesh::compute_bounds() for(size_t i = 0; i < curve_keys_size; i++) bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w); - if (use_motion_blur && attr) { + if(use_motion_blur && attr) { size_t steps_size = verts.size() * (motion_steps - 1); float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow_safe(vert_steps[i]); } - if (use_motion_blur && curve_attr) { + if(use_motion_blur && curve_attr) { size_t steps_size = curve_keys.size() * (motion_steps - 1); float3 *key_steps = curve_attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow_safe(key_steps[i]); } } @@ -508,7 +513,6 @@ void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total progress->set_status(msg, "Building BVH"); BVHParams bparams; - bparams.use_cache = params->use_bvh_cache; bparams.use_spatial_split = params->use_bvh_spatial_split; bparams.use_qbvh = params->use_qbvh; @@ -553,6 +557,7 @@ MeshManager::MeshManager() { bvh = NULL; need_update = true; + need_flags_update = true; } MeshManager::~MeshManager() @@ -649,6 +654,10 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att } } } +#else + (void)device; + (void)scene; + (void)mesh_attributes; #endif } @@ -746,8 +755,49 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce device->tex_alloc("__attributes_map", dscene->attributes_map); } -static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_float, vector<float4>& attr_float3, vector<uchar4>& attr_uchar4, - Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element) +static void update_attribute_element_size(Mesh *mesh, + Attribute *mattr, + size_t *attr_float_size, + size_t *attr_float3_size, + size_t *attr_uchar4_size) +{ + if(mattr) { + size_t size = mattr->element_size( + mesh->verts.size(), + mesh->triangles.size(), + mesh->motion_steps, + mesh->curves.size(), + mesh->curve_keys.size()); + + if(mattr->element == ATTR_ELEMENT_VOXEL) { + /* pass */ + } + else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) { + *attr_uchar4_size += size; + } + else if(mattr->type == TypeDesc::TypeFloat) { + *attr_float_size += size; + } + else if(mattr->type == TypeDesc::TypeMatrix) { + *attr_float3_size += size * 4; + } + else { + *attr_float3_size += size; + } + } +} + +static void update_attribute_element_offset(Mesh *mesh, + vector<float>& attr_float, + size_t& attr_float_offset, + vector<float4>& attr_float3, + size_t& attr_float3_offset, + vector<uchar4>& attr_uchar4, + size_t& attr_uchar4_offset, + Attribute *mattr, + TypeDesc& type, + int& offset, + AttributeElement& element) { if(mattr) { /* store element and type */ @@ -769,39 +819,43 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa } else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) { uchar4 *data = mattr->data_uchar4(); - offset = attr_uchar4.size(); - - attr_uchar4.resize(attr_uchar4.size() + size); + offset = attr_uchar4_offset; - for(size_t k = 0; k < size; k++) + assert(attr_uchar4.capacity() >= offset + size); + for(size_t k = 0; k < size; k++) { attr_uchar4[offset+k] = data[k]; + } + attr_uchar4_offset += size; } else if(mattr->type == TypeDesc::TypeFloat) { float *data = mattr->data_float(); - offset = attr_float.size(); + offset = attr_float_offset; - attr_float.resize(attr_float.size() + size); - - for(size_t k = 0; k < size; k++) + assert(attr_float.capacity() >= offset + size); + for(size_t k = 0; k < size; k++) { attr_float[offset+k] = data[k]; + } + attr_float_offset += size; } else if(mattr->type == TypeDesc::TypeMatrix) { Transform *tfm = mattr->data_transform(); - offset = attr_float3.size(); - - attr_float3.resize(attr_float3.size() + size*4); + offset = attr_float3_offset; - for(size_t k = 0; k < size*4; k++) + assert(attr_float3.capacity() >= offset + size * 4); + for(size_t k = 0; k < size*4; k++) { attr_float3[offset+k] = (&tfm->x)[k]; + } + attr_float3_offset += size * 4; } else { float4 *data = mattr->data_float4(); - offset = attr_float3.size(); - - attr_float3.resize(attr_float3.size() + size); + offset = attr_float3_offset; - for(size_t k = 0; k < size; k++) + assert(attr_float3.capacity() >= offset + size); + for(size_t k = 0; k < size; k++) { attr_float3[offset+k] = data[k]; + } + attr_float3_offset += size; } /* mesh vertex/curve index is global, not per object, so we sneak @@ -851,16 +905,16 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, /* 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 * maps next */ - vector<float> attr_float; - vector<float4> attr_float3; - vector<uchar4> attr_uchar4; + /* Pre-allocate attributes to avoid arrays re-allocation which would + * take 2x of overall attribute memory usage. + */ + size_t attr_float_size = 0; + size_t attr_float3_size = 0; + size_t attr_uchar4_size = 0; for(size_t i = 0; i < scene->meshes.size(); i++) { Mesh *mesh = scene->meshes[i]; AttributeRequestSet& attributes = mesh_attributes[i]; - - /* todo: we now store std and name attributes from requests even if - * they actually refer to the same mesh attributes, optimize */ foreach(AttributeRequest& req, attributes.requests) { Attribute *triangle_mattr = mesh->attributes.find(req); Attribute *curve_mattr = mesh->curve_attributes.find(req); @@ -874,12 +928,56 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size()); } - update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, triangle_mattr, - req.triangle_type, req.triangle_offset, req.triangle_element); + update_attribute_element_size(mesh, + triangle_mattr, + &attr_float_size, + &attr_float3_size, + &attr_uchar4_size); + update_attribute_element_size(mesh, + curve_mattr, + &attr_float_size, + &attr_float3_size, + &attr_uchar4_size); + } + } + + vector<float> attr_float(attr_float_size); + vector<float4> attr_float3(attr_float3_size); + vector<uchar4> attr_uchar4(attr_uchar4_size); + + size_t attr_float_offset = 0; + size_t attr_float3_offset = 0; + size_t attr_uchar4_offset = 0; + + /* Fill in attributes. */ + for(size_t i = 0; i < scene->meshes.size(); i++) { + Mesh *mesh = scene->meshes[i]; + AttributeRequestSet& attributes = mesh_attributes[i]; + + /* todo: we now store std and name attributes from requests even if + * they actually refer to the same mesh attributes, optimize */ + foreach(AttributeRequest& req, attributes.requests) { + Attribute *triangle_mattr = mesh->attributes.find(req); + Attribute *curve_mattr = mesh->curve_attributes.find(req); + + update_attribute_element_offset(mesh, + attr_float, attr_float_offset, + attr_float3, attr_float3_offset, + attr_uchar4, attr_uchar4_offset, + triangle_mattr, + req.triangle_type, + req.triangle_offset, + req.triangle_element); + + update_attribute_element_offset(mesh, + attr_float, attr_float_offset, + attr_float3, attr_float3_offset, + attr_uchar4, attr_uchar4_offset, + curve_mattr, + req.curve_type, + req.curve_offset, + req.curve_element); - update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, curve_mattr, - req.curve_type, req.curve_offset, req.curve_element); - if(progress.get_cancel()) return; } } @@ -978,11 +1076,13 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * /* bvh build */ progress.set_status("Updating Scene BVH", "Building"); + VLOG(1) << (scene->params.use_qbvh ? "Using QBVH optimization structure" + : "Using regular BVH optimization structure"); + BVHParams bparams; bparams.top_level = true; bparams.use_qbvh = scene->params.use_qbvh; bparams.use_spatial_split = scene->params.use_bvh_spatial_split; - bparams.use_cache = scene->params.use_bvh_cache; delete bvh; bvh = BVH::create(bparams, scene->objects); @@ -999,6 +1099,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * dscene->bvh_nodes.reference((float4*)&pack.nodes[0], pack.nodes.size()); device->tex_alloc("__bvh_nodes", dscene->bvh_nodes); } + if(pack.leaf_nodes.size()) { + dscene->bvh_leaf_nodes.reference((float4*)&pack.leaf_nodes[0], pack.leaf_nodes.size()); + device->tex_alloc("__bvh_leaf_nodes", dscene->bvh_leaf_nodes); + } if(pack.object_node.size()) { dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size()); device->tex_alloc("__object_node", dscene->object_node); @@ -1025,18 +1129,91 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * } dscene->data.bvh.root = pack.root_index; + dscene->data.bvh.use_qbvh = scene->params.use_qbvh; +} + +void MeshManager::device_update_flags(Device * /*device*/, + DeviceScene * /*dscene*/, + Scene * scene, + Progress& /*progress*/) +{ + if(!need_update && !need_flags_update) { + return; + } + /* update flags */ + foreach(Mesh *mesh, scene->meshes) { + mesh->has_volume = false; + foreach(uint shader, mesh->used_shaders) { + if(scene->shaders[shader]->has_volume) { + mesh->has_volume = true; + } + } + } + need_flags_update = false; +} + +void MeshManager::device_update_displacement_images(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress& progress) +{ + progress.set_status("Updating Displacement Images"); + TaskPool pool; + ImageManager *image_manager = scene->image_manager; + set<int> bump_images; + foreach(Mesh *mesh, scene->meshes) { + if(mesh->need_update) { + foreach(uint shader_index, mesh->used_shaders) { + Shader *shader = scene->shaders[shader_index]; + if(shader->graph_bump == NULL) { + continue; + } + foreach(ShaderNode* node, shader->graph_bump->nodes) { + if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) { + continue; + } + if(device->info.pack_images) { + /* If device requires packed images we need to update all + * images now, even if they're not used for displacement. + */ + image_manager->device_update(device, + dscene, + progress); + return; + } + ImageSlotNode *image_node = static_cast<ImageSlotNode*>(node); + int slot = image_node->slot; + if(slot != -1) { + bump_images.insert(slot); + } + } + } + } + } + foreach(int slot, bump_images) { + pool.push(function_bind(&ImageManager::device_update_slot, + image_manager, + device, + dscene, + slot, + &progress)); + } + pool.wait_work(); } void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + VLOG(1) << "Total " << scene->meshes.size() << " meshes."; + if(!need_update) return; /* update normals */ foreach(Mesh *mesh, scene->meshes) { - foreach(uint shader, mesh->used_shaders) + foreach(uint shader, mesh->used_shaders) { if(scene->shaders[shader]->need_update_attributes) mesh->need_update = true; + } if(mesh->need_update) { mesh->add_face_normals(); @@ -1046,6 +1223,28 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen } } + /* Update images needed for true displacement. */ + bool need_displacement_images = false; + bool old_need_object_flags_update = false; + foreach(Mesh *mesh, scene->meshes) { + if(mesh->need_update && + mesh->displacement_method != Mesh::DISPLACE_BUMP) + { + need_displacement_images = true; + break; + } + } + if(need_displacement_images) { + VLOG(1) << "Updating images used for true displacement."; + device_update_displacement_images(device, dscene, scene, progress); + old_need_object_flags_update = scene->object_manager->need_flags_update; + scene->object_manager->device_update_flags(device, + dscene, + scene, + progress, + false); + } + /* device update */ device_free(device, dscene); @@ -1087,13 +1286,19 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen foreach(Mesh *mesh, scene->meshes) { if(mesh->need_update) { - pool.push(function_bind(&Mesh::compute_bvh, mesh, &scene->params, &progress, i, num_bvh)); - i++; + pool.push(function_bind(&Mesh::compute_bvh, + mesh, + &scene->params, + &progress, + i, + num_bvh)); + if(!mesh->transform_applied) { + i++; + } } } pool.wait_work(); - foreach(Shader *shader, scene->shaders) shader->need_update_attributes = false; @@ -1104,6 +1309,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen bool motion_blur = false; #endif + /* update obejcts */ + vector<Object *> volume_objects; foreach(Object *object, scene->objects) object->compute_bounds(motion_blur); @@ -1112,11 +1319,22 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen device_update_bvh(device, dscene, scene, progress); need_update = false; + + if(need_displacement_images) { + /* Re-tag flags for update, so they're re-evaluated + * for meshes with correct bounding boxes. + * + * This wouldn't cause wrong results, just true + * displacement might be less optimal ot calculate. + */ + scene->object_manager->need_flags_update = old_need_object_flags_update; + } } void MeshManager::device_free(Device *device, DeviceScene *dscene) { device->tex_free(dscene->bvh_nodes); + device->tex_free(dscene->bvh_leaf_nodes); device->tex_free(dscene->object_node); device->tex_free(dscene->tri_woop); device->tex_free(dscene->prim_type); |