diff options
author | Brecht Van Lommel <brecht@blender.org> | 2021-03-01 01:23:24 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-10-06 18:52:04 +0300 |
commit | 04857cc8efb385af5d8f40b655eeca41e2b73494 (patch) | |
tree | b16edec8a0e91fddfa050b2e8b747ca194c0b622 /intern/cycles/render | |
parent | 0fd0b0643a7a1c0334f39bddba4067d8fa8eede6 (diff) |
Cycles: fully decouple triangle and curve primitive storage from BVH2
Previously the storage here was optimized to avoid indirections in BVH2
traversal. This helps improve performance a bit, but makes performance
and memory usage of Embree and OptiX BVHs a bit worse also. It also adds
code complexity in other parts of the code.
Now decouple triangle and curve primitive storage from BVH2.
* Reduced peak memory usage on all devices
* Bit better performance for OptiX and Embree
* Bit worse performance for CUDA
* Simplified code:
** Intersection.prim/object now matches ShaderData.prim/object
** No more offset manipulation for mesh displacement before a BVH is built
** Remove primitive packing code and flags for Embree and OptiX
** Curve segments are now stored in a KernelCurve struct
* Also happens to fix a bug in baking with incorrect prim/object
Fixes T91968, T91770, T91902
Differential Revision: https://developer.blender.org/D12766
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/geometry.cpp | 244 | ||||
-rw-r--r-- | intern/cycles/render/geometry.h | 30 | ||||
-rw-r--r-- | intern/cycles/render/hair.cpp | 70 | ||||
-rw-r--r-- | intern/cycles/render/hair.h | 15 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 69 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 16 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 6 |
9 files changed, 113 insertions, 345 deletions
diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 4de458de271..49b5f9e27ee 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -46,12 +46,6 @@ CCL_NAMESPACE_BEGIN /* Geometry */ -PackFlags operator|=(PackFlags &pack_flags, uint32_t value) -{ - pack_flags = (PackFlags)((uint32_t)pack_flags | value); - return pack_flags; -} - NODE_ABSTRACT_DEFINE(Geometry) { NodeType *type = NodeType::add("geometry_base", NULL); @@ -79,7 +73,6 @@ Geometry::Geometry(const NodeType *node_type, const Type type) bvh = NULL; attr_map_offset = 0; - optix_prim_offset = 0; prim_offset = 0; } @@ -707,9 +700,9 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom, if (element == ATTR_ELEMENT_CURVE) offset -= hair->prim_offset; else if (element == ATTR_ELEMENT_CURVE_KEY) - offset -= hair->curvekey_offset; + offset -= hair->curve_key_offset; else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION) - offset -= hair->curvekey_offset; + offset -= hair->curve_key_offset; } } else { @@ -972,28 +965,22 @@ void GeometryManager::mesh_calc_offset(Scene *scene, BVHLayout bvh_layout) size_t vert_size = 0; size_t tri_size = 0; - size_t curve_key_size = 0; size_t curve_size = 0; + size_t curve_key_size = 0; + size_t curve_segment_size = 0; size_t patch_size = 0; size_t face_size = 0; size_t corner_size = 0; - size_t optix_prim_size = 0; - foreach (Geometry *geom, scene->geometry) { - if (geom->optix_prim_offset != optix_prim_size) { - /* Need to rebuild BVH in OptiX, since refit only allows modified mesh data there */ - const bool has_optix_bvh = bvh_layout == BVH_LAYOUT_OPTIX || - bvh_layout == BVH_LAYOUT_MULTI_OPTIX || - bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE; - geom->need_update_rebuild |= has_optix_bvh; - geom->need_update_bvh_for_offset = true; - } + bool prim_offset_changed = false; if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); + prim_offset_changed = (mesh->prim_offset != tri_size); + mesh->vert_offset = vert_size; mesh->prim_offset = tri_size; @@ -1017,27 +1004,35 @@ void GeometryManager::mesh_calc_offset(Scene *scene, BVHLayout bvh_layout) face_size += mesh->get_num_subd_faces(); corner_size += mesh->subd_face_corners.size(); - - mesh->optix_prim_offset = optix_prim_size; - optix_prim_size += mesh->num_triangles(); } else if (geom->is_hair()) { Hair *hair = static_cast<Hair *>(geom); - hair->curvekey_offset = curve_key_size; + prim_offset_changed = (hair->curve_segment_offset != curve_segment_size); + hair->curve_key_offset = curve_key_size; + hair->curve_segment_offset = curve_segment_size; hair->prim_offset = curve_size; - curve_key_size += hair->get_curve_keys().size(); curve_size += hair->num_curves(); + curve_key_size += hair->get_curve_keys().size(); + curve_segment_size += hair->num_segments(); + } - hair->optix_prim_offset = optix_prim_size; - optix_prim_size += hair->num_segments(); + if (prim_offset_changed) { + /* Need to rebuild BVH in OptiX, since refit only allows modified mesh data there */ + const bool has_optix_bvh = bvh_layout == BVH_LAYOUT_OPTIX || + bvh_layout == BVH_LAYOUT_MULTI_OPTIX || + bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE; + geom->need_update_rebuild |= has_optix_bvh; + geom->need_update_bvh_for_offset = true; } } } -void GeometryManager::device_update_mesh( - Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress) +void GeometryManager::device_update_mesh(Device *, + DeviceScene *dscene, + Scene *scene, + Progress &progress) { /* Count. */ size_t vert_size = 0; @@ -1045,6 +1040,7 @@ void GeometryManager::device_update_mesh( size_t curve_key_size = 0; size_t curve_size = 0; + size_t curve_segment_size = 0; size_t patch_size = 0; @@ -1071,31 +1067,7 @@ void GeometryManager::device_update_mesh( curve_key_size += hair->get_curve_keys().size(); curve_size += hair->num_curves(); - } - } - - /* Create mapping from triangle to primitive triangle array. */ - vector<uint> tri_prim_index(tri_size); - if (for_displacement) { - /* For displacement kernels we do some trickery to make them believe - * 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 - * really use same semantic of arrays. - */ - foreach (Geometry *geom, scene->geometry) { - if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { - Mesh *mesh = static_cast<Mesh *>(geom); - for (size_t i = 0; i < mesh->num_triangles(); ++i) { - tri_prim_index[i + mesh->prim_offset] = 3 * (i + mesh->prim_offset); - } - } - } - } - else { - for (size_t i = 0; i < dscene->prim_index.size(); ++i) { - if ((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { - tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i]; - } + curve_segment_size += hair->num_segments(); } } @@ -1104,6 +1076,7 @@ void GeometryManager::device_update_mesh( /* normals */ progress.set_status("Updating Mesh", "Computing normals"); + float4 *tri_verts = dscene->tri_verts.alloc(tri_size * 3); uint *tri_shader = dscene->tri_shader.alloc(tri_size); float4 *vnormal = dscene->tri_vnormal.alloc(vert_size); uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size); @@ -1129,13 +1102,12 @@ void GeometryManager::device_update_mesh( mesh->pack_normals(&vnormal[mesh->vert_offset]); } - if (mesh->triangles_is_modified() || mesh->vert_patch_uv_is_modified() || copy_all_data) { - mesh->pack_verts(tri_prim_index, + if (mesh->verts_is_modified() || mesh->triangles_is_modified() || + mesh->vert_patch_uv_is_modified() || copy_all_data) { + mesh->pack_verts(&tri_verts[mesh->prim_offset * 3], &tri_vindex[mesh->prim_offset], &tri_patch[mesh->prim_offset], - &tri_patch_uv[mesh->vert_offset], - mesh->vert_offset, - mesh->prim_offset); + &tri_patch_uv[mesh->vert_offset]); } if (progress.get_cancel()) @@ -1146,6 +1118,7 @@ void GeometryManager::device_update_mesh( /* vertex coordinates */ progress.set_status("Updating Mesh", "Copying Mesh to device"); + dscene->tri_verts.copy_to_device_if_modified(); dscene->tri_shader.copy_to_device_if_modified(); dscene->tri_vnormal.copy_to_device_if_modified(); dscene->tri_vindex.copy_to_device_if_modified(); @@ -1153,13 +1126,16 @@ void GeometryManager::device_update_mesh( dscene->tri_patch_uv.copy_to_device_if_modified(); } - if (curve_size != 0) { - progress.set_status("Updating Mesh", "Copying Strands to device"); + if (curve_segment_size != 0) { + progress.set_status("Updating Mesh", "Copying Curves to device"); float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size); - float4 *curves = dscene->curves.alloc(curve_size); + KernelCurve *curves = dscene->curves.alloc(curve_size); + KernelCurveSegment *curve_segments = dscene->curve_segments.alloc(curve_segment_size); - const bool copy_all_data = dscene->curve_keys.need_realloc() || dscene->curves.need_realloc(); + const bool copy_all_data = dscene->curve_keys.need_realloc() || + dscene->curves.need_realloc() || + dscene->curve_segments.need_realloc(); foreach (Geometry *geom, scene->geometry) { if (geom->is_hair()) { @@ -1175,9 +1151,9 @@ void GeometryManager::device_update_mesh( } hair->pack_curves(scene, - &curve_keys[hair->curvekey_offset], + &curve_keys[hair->curve_key_offset], &curves[hair->prim_offset], - hair->curvekey_offset); + &curve_segments[hair->curve_segment_offset]); if (progress.get_cancel()) return; } @@ -1185,6 +1161,7 @@ void GeometryManager::device_update_mesh( dscene->curve_keys.copy_to_device_if_modified(); dscene->curves.copy_to_device_if_modified(); + dscene->curve_segments.copy_to_device_if_modified(); } if (patch_size != 0 && dscene->patches.need_realloc()) { @@ -1195,10 +1172,7 @@ void GeometryManager::device_update_mesh( foreach (Geometry *geom, scene->geometry) { if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); - mesh->pack_patches(&patch_data[mesh->patch_offset], - mesh->vert_offset, - mesh->face_offset, - mesh->corner_offset); + mesh->pack_patches(&patch_data[mesh->patch_offset]); if (mesh->patch_table) { mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], @@ -1212,23 +1186,6 @@ void GeometryManager::device_update_mesh( dscene->patches.copy_to_device(); } - - if (for_displacement) { - float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3); - foreach (Geometry *geom, scene->geometry) { - if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { - Mesh *mesh = static_cast<Mesh *>(geom); - for (size_t i = 0; i < mesh->num_triangles(); ++i) { - Mesh::Triangle t = mesh->get_triangle(i); - 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 + 1] = float3_to_float4(mesh->verts[t.v[1]]); - prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]); - } - } - } - dscene->prim_tri_verts.copy_to_device(); - } } void GeometryManager::device_update_bvh(Device *device, @@ -1256,16 +1213,6 @@ void GeometryManager::device_update_bvh(Device *device, const bool can_refit = scene->bvh != nullptr && (bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX); - PackFlags pack_flags = PackFlags::PACK_NONE; - - if (scene->bvh == nullptr) { - pack_flags |= PackFlags::PACK_ALL; - } - - if (dscene->prim_visibility.is_modified()) { - pack_flags |= PackFlags::PACK_VISIBILITY; - } - BVH *bvh = scene->bvh; if (!scene->bvh) { bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device); @@ -1284,77 +1231,7 @@ void GeometryManager::device_update_bvh(Device *device, pack = std::move(static_cast<BVH2 *>(bvh)->pack); } else { - progress.set_status("Updating Scene BVH", "Packing BVH primitives"); - - size_t num_prims = 0; - size_t num_tri_verts = 0; - foreach (Geometry *geom, scene->geometry) { - if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { - Mesh *mesh = static_cast<Mesh *>(geom); - num_prims += mesh->num_triangles(); - num_tri_verts += 3 * mesh->num_triangles(); - } - else if (geom->is_hair()) { - Hair *hair = static_cast<Hair *>(geom); - num_prims += hair->num_segments(); - } - } - pack.root_index = -1; - - if (pack_flags != PackFlags::PACK_ALL) { - /* if we do not need to recreate the BVH, then only the vertices are updated, so we can - * safely retake the memory */ - dscene->prim_tri_verts.give_data(pack.prim_tri_verts); - - if ((pack_flags & PackFlags::PACK_VISIBILITY) != 0) { - dscene->prim_visibility.give_data(pack.prim_visibility); - } - } - else { - /* It is not strictly necessary to skip those resizes we if do not have to repack, as the OS - * will not allocate pages if we do not touch them, however it does help catching bugs. */ - pack.prim_tri_index.resize(num_prims); - pack.prim_tri_verts.resize(num_tri_verts); - pack.prim_type.resize(num_prims); - pack.prim_index.resize(num_prims); - pack.prim_object.resize(num_prims); - pack.prim_visibility.resize(num_prims); - } - - // 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; - geometry_to_object_info.reserve(scene->geometry.size()); - foreach (Object *ob, scene->objects) { - const Geometry *const geom = ob->get_geometry(); - pair<int, uint> &info = geometry_to_object_info[geom]; - info.second |= ob->visibility_for_tracing(); - if (!geom->is_instanced()) { - info.first = ob->get_device_index(); - } - } - - TaskPool pool; - // 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. - foreach (Geometry *geom, scene->geometry) { - /* Make a copy of the pack_flags so the current geometry's flags do not pollute the others'. - */ - PackFlags geom_pack_flags = pack_flags; - - if (geom->is_modified()) { - geom_pack_flags |= PackFlags::PACK_VERTICES; - } - - if (geom_pack_flags == PACK_NONE) { - continue; - } - - const pair<int, uint> &info = geometry_to_object_info[geom]; - pool.push(function_bind( - &Geometry::pack_primitives, geom, &pack, info.first, info.second, geom_pack_flags)); - } - pool.wait_work(); } /* copy to device */ @@ -1375,31 +1252,23 @@ void GeometryManager::device_update_bvh(Device *device, dscene->object_node.steal_data(pack.object_node); dscene->object_node.copy_to_device(); } - if (pack.prim_tri_index.size() && (dscene->prim_tri_index.need_realloc() || has_bvh2_layout)) { - dscene->prim_tri_index.steal_data(pack.prim_tri_index); - dscene->prim_tri_index.copy_to_device(); - } - if (pack.prim_tri_verts.size()) { - dscene->prim_tri_verts.steal_data(pack.prim_tri_verts); - dscene->prim_tri_verts.copy_to_device(); - } - if (pack.prim_type.size() && (dscene->prim_type.need_realloc() || has_bvh2_layout)) { + if (pack.prim_type.size()) { dscene->prim_type.steal_data(pack.prim_type); dscene->prim_type.copy_to_device(); } - if (pack.prim_visibility.size() && (dscene->prim_visibility.is_modified() || has_bvh2_layout)) { + if (pack.prim_visibility.size()) { dscene->prim_visibility.steal_data(pack.prim_visibility); dscene->prim_visibility.copy_to_device(); } - if (pack.prim_index.size() && (dscene->prim_index.need_realloc() || has_bvh2_layout)) { + if (pack.prim_index.size()) { dscene->prim_index.steal_data(pack.prim_index); dscene->prim_index.copy_to_device(); } - if (pack.prim_object.size() && (dscene->prim_object.need_realloc() || has_bvh2_layout)) { + if (pack.prim_object.size()) { dscene->prim_object.steal_data(pack.prim_object); dscene->prim_object.copy_to_device(); } - if (pack.prim_time.size() && (dscene->prim_time.need_realloc() || has_bvh2_layout)) { + if (pack.prim_time.size()) { dscene->prim_time.steal_data(pack.prim_time); dscene->prim_time.copy_to_device(); } @@ -1629,8 +1498,6 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro dscene->bvh_nodes.tag_realloc(); dscene->bvh_leaf_nodes.tag_realloc(); dscene->object_node.tag_realloc(); - dscene->prim_tri_verts.tag_realloc(); - dscene->prim_tri_index.tag_realloc(); dscene->prim_type.tag_realloc(); dscene->prim_visibility.tag_realloc(); dscene->prim_index.tag_realloc(); @@ -1649,6 +1516,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro if (device_update_flags & DEVICE_CURVE_DATA_NEEDS_REALLOC) { dscene->curves.tag_realloc(); dscene->curve_keys.tag_realloc(); + dscene->curve_segments.tag_realloc(); } } @@ -1691,6 +1559,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro if (device_update_flags & DEVICE_MESH_DATA_MODIFIED) { /* if anything else than vertices or shaders are modified, we would need to reallocate, so * these are the only arrays that can be updated */ + dscene->tri_verts.tag_modified(); dscene->tri_vnormal.tag_modified(); dscene->tri_shader.tag_modified(); } @@ -1698,6 +1567,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro if (device_update_flags & DEVICE_CURVE_DATA_MODIFIED) { dscene->curve_keys.tag_modified(); dscene->curves.tag_modified(); + dscene->curve_segments.tag_modified(); } need_flags_update = false; @@ -1906,7 +1776,7 @@ void GeometryManager::device_update(Device *device, {"device_update (displacement: copy meshes to device)", time}); } }); - device_update_mesh(device, dscene, scene, true, progress); + device_update_mesh(device, dscene, scene, progress); } if (progress.get_cancel()) { return; @@ -2058,7 +1928,7 @@ void GeometryManager::device_update(Device *device, {"device_update (copy meshes to device)", time}); } }); - device_update_mesh(device, dscene, scene, false, progress); + device_update_mesh(device, dscene, scene, progress); if (progress.get_cancel()) { return; } @@ -2091,13 +1961,12 @@ void GeometryManager::device_update(Device *device, dscene->bvh_nodes.clear_modified(); dscene->bvh_leaf_nodes.clear_modified(); dscene->object_node.clear_modified(); - dscene->prim_tri_verts.clear_modified(); - dscene->prim_tri_index.clear_modified(); dscene->prim_type.clear_modified(); dscene->prim_visibility.clear_modified(); dscene->prim_index.clear_modified(); dscene->prim_object.clear_modified(); dscene->prim_time.clear_modified(); + dscene->tri_verts.clear_modified(); dscene->tri_shader.clear_modified(); dscene->tri_vindex.clear_modified(); dscene->tri_patch.clear_modified(); @@ -2105,6 +1974,7 @@ void GeometryManager::device_update(Device *device, dscene->tri_patch_uv.clear_modified(); dscene->curves.clear_modified(); dscene->curve_keys.clear_modified(); + dscene->curve_segments.clear_modified(); dscene->patches.clear_modified(); dscene->attributes_map.clear_modified(); dscene->attributes_float.clear_modified(); @@ -2118,13 +1988,12 @@ void GeometryManager::device_free(Device *device, DeviceScene *dscene, bool forc dscene->bvh_nodes.free_if_need_realloc(force_free); dscene->bvh_leaf_nodes.free_if_need_realloc(force_free); dscene->object_node.free_if_need_realloc(force_free); - dscene->prim_tri_verts.free_if_need_realloc(force_free); - dscene->prim_tri_index.free_if_need_realloc(force_free); dscene->prim_type.free_if_need_realloc(force_free); dscene->prim_visibility.free_if_need_realloc(force_free); dscene->prim_index.free_if_need_realloc(force_free); dscene->prim_object.free_if_need_realloc(force_free); dscene->prim_time.free_if_need_realloc(force_free); + dscene->tri_verts.free_if_need_realloc(force_free); dscene->tri_shader.free_if_need_realloc(force_free); dscene->tri_vnormal.free_if_need_realloc(force_free); dscene->tri_vindex.free_if_need_realloc(force_free); @@ -2132,6 +2001,7 @@ void GeometryManager::device_free(Device *device, DeviceScene *dscene, bool forc dscene->tri_patch_uv.free_if_need_realloc(force_free); dscene->curves.free_if_need_realloc(force_free); dscene->curve_keys.free_if_need_realloc(force_free); + dscene->curve_segments.free_if_need_realloc(force_free); dscene->patches.free_if_need_realloc(force_free); dscene->attributes_map.free_if_need_realloc(force_free); dscene->attributes_float.free_if_need_realloc(force_free); diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h index 7db122f69cb..cd42f62c669 100644 --- a/intern/cycles/render/geometry.h +++ b/intern/cycles/render/geometry.h @@ -43,24 +43,6 @@ class Shader; class Volume; struct PackedBVH; -/* Flags used to determine which geometry data need to be packed. */ -enum PackFlags : uint32_t { - PACK_NONE = 0u, - - /* Pack the geometry information (e.g. triangle or curve keys indices). */ - PACK_GEOMETRY = (1u << 0), - - /* Pack the vertices, for Meshes and Volumes' bounding meshes. */ - PACK_VERTICES = (1u << 1), - - /* Pack the visibility flags for each triangle or curve. */ - PACK_VISIBILITY = (1u << 2), - - PACK_ALL = (PACK_GEOMETRY | PACK_VERTICES | PACK_VISIBILITY), -}; - -PackFlags operator|=(PackFlags &pack_flags, uint32_t value); - /* Geometry * * Base class for geometric types like Mesh and Hair. */ @@ -100,7 +82,6 @@ class Geometry : public Node { BVH *bvh; size_t attr_map_offset; size_t prim_offset; - size_t optix_prim_offset; /* Shader Properties */ bool has_volume; /* Set in the device_update_flags(). */ @@ -144,10 +125,7 @@ class Geometry : public Node { int n, int total); - virtual void pack_primitives(PackedBVH *pack, - int object, - uint visibility, - PackFlags pack_flags) = 0; + virtual PrimitiveType primitive_type() const = 0; /* Check whether the geometry should have own BVH built separately. Briefly, * own BVH is needed for geometry, if: @@ -260,11 +238,7 @@ class GeometryManager { void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - void device_update_mesh(Device *device, - DeviceScene *dscene, - Scene *scene, - bool for_displacement, - Progress &progress); + void device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); void device_update_attributes(Device *device, DeviceScene *dscene, diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp index 72fc612c0c0..e104455f7dd 100644 --- a/intern/cycles/render/hair.cpp +++ b/intern/cycles/render/hair.cpp @@ -295,7 +295,8 @@ NODE_DEFINE(Hair) Hair::Hair() : Geometry(get_node_type(), Geometry::HAIR) { - curvekey_offset = 0; + curve_key_offset = 0; + curve_segment_offset = 0; curve_shape = CURVE_RIBBON; } @@ -462,8 +463,8 @@ void Hair::apply_transform(const Transform &tfm, const bool apply_to_motion) void Hair::pack_curves(Scene *scene, float4 *curve_key_co, - float4 *curve_data, - size_t curvekey_offset) + KernelCurve *curves, + KernelCurveSegment *curve_segments) { size_t curve_keys_size = curve_keys.size(); @@ -477,7 +478,10 @@ void Hair::pack_curves(Scene *scene, } /* pack curve segments */ + const PrimitiveType type = primitive_type(); + size_t curve_num = num_curves(); + size_t index = 0; for (size_t i = 0; i < curve_num; i++) { Curve curve = get_curve(i); @@ -487,56 +491,24 @@ void Hair::pack_curves(Scene *scene, scene->default_surface; shader_id = scene->shader_manager->get_shader_id(shader, false); - curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset), - __int_as_float(curve.num_keys), - __int_as_float(shader_id), - 0.0f); - } -} + curves[i].shader_id = shader_id; + curves[i].first_key = curve_key_offset + curve.first_key; + curves[i].num_keys = curve.num_keys; + curves[i].type = type; -void Hair::pack_primitives(PackedBVH *pack, int object, uint visibility, PackFlags pack_flags) -{ - if (curve_first_key.empty()) - return; - - /* Separate loop as other arrays are not initialized if their packing is not required. */ - if ((pack_flags & PACK_VISIBILITY) != 0) { - unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset]; - - size_t index = 0; - for (size_t j = 0; j < num_curves(); ++j) { - Curve curve = get_curve(j); - for (size_t k = 0; k < curve.num_segments(); ++k, ++index) { - prim_visibility[index] = visibility; - } + for (int k = 0; k < curve.num_segments(); ++k, ++index) { + curve_segments[index].prim = prim_offset + i; + curve_segments[index].type = PRIMITIVE_PACK_SEGMENT(type, k); } } +} - if ((pack_flags & PACK_GEOMETRY) != 0) { - unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset]; - int *prim_type = &pack->prim_type[optix_prim_offset]; - int *prim_index = &pack->prim_index[optix_prim_offset]; - int *prim_object = &pack->prim_object[optix_prim_offset]; - // 'pack->prim_time' is unused by Embree and OptiX - - uint type = has_motion_blur() ? - ((curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON : - PRIMITIVE_MOTION_CURVE_THICK) : - ((curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : - PRIMITIVE_CURVE_THICK); - - size_t index = 0; - for (size_t j = 0; j < num_curves(); ++j) { - Curve curve = get_curve(j); - for (size_t k = 0; k < curve.num_segments(); ++k, ++index) { - prim_tri_index[index] = -1; - prim_type[index] = PRIMITIVE_PACK_SEGMENT(type, k); - // Each curve segment points back to its curve index - prim_index[index] = j + prim_offset; - prim_object[index] = object; - } - } - } +PrimitiveType Hair::primitive_type() const +{ + return has_motion_blur() ? + ((curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON : + PRIMITIVE_MOTION_CURVE_THICK) : + ((curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK); } CCL_NAMESPACE_END diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h index e4451d70767..920e9601b35 100644 --- a/intern/cycles/render/hair.h +++ b/intern/cycles/render/hair.h @@ -21,6 +21,8 @@ CCL_NAMESPACE_BEGIN +struct KernelCurveSegment; + class Hair : public Geometry { public: NODE_DECLARE @@ -95,7 +97,8 @@ class Hair : public Geometry { NODE_SOCKET_API_ARRAY(array<int>, curve_shader) /* BVH */ - size_t curvekey_offset; + size_t curve_key_offset; + size_t curve_segment_offset; CurveShapeType curve_shape; /* Constructor/Destructor */ @@ -144,12 +147,12 @@ class Hair : public Geometry { void get_uv_tiles(ustring map, unordered_set<int> &tiles) override; /* BVH */ - void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset); + void pack_curves(Scene *scene, + float4 *curve_key_co, + KernelCurve *curve, + KernelCurveSegment *curve_segments); - void pack_primitives(PackedBVH *pack, - int object, - uint visibility, - PackFlags pack_flags) override; + PrimitiveType primitive_type() const override; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index fd9879dd5dd..2ecea3101db 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -729,12 +729,7 @@ void Mesh::pack_normals(float4 *vnormal) } } -void Mesh::pack_verts(const vector<uint> &tri_prim_index, - uint4 *tri_vindex, - uint *tri_patch, - float2 *tri_patch_uv, - size_t vert_offset, - size_t tri_offset) +void Mesh::pack_verts(float4 *tri_verts, uint4 *tri_vindex, uint *tri_patch, float2 *tri_patch_uv) { size_t verts_size = verts.size(); @@ -749,17 +744,19 @@ void Mesh::pack_verts(const vector<uint> &tri_prim_index, size_t triangles_size = num_triangles(); for (size_t i = 0; i < triangles_size; i++) { - Triangle t = get_triangle(i); - tri_vindex[i] = make_uint4(t.v[0] + vert_offset, - t.v[1] + vert_offset, - t.v[2] + vert_offset, - tri_prim_index[i + tri_offset]); + const Triangle t = get_triangle(i); + tri_vindex[i] = make_uint4( + t.v[0] + vert_offset, t.v[1] + vert_offset, t.v[2] + vert_offset, 3 * (prim_offset + i)); tri_patch[i] = (!get_num_subd_faces()) ? -1 : (triangle_patch[i] * 8 + patch_offset); + + tri_verts[i * 3] = float3_to_float4(verts[t.v[0]]); + tri_verts[i * 3 + 1] = float3_to_float4(verts[t.v[1]]); + tri_verts[i * 3 + 2] = float3_to_float4(verts[t.v[2]]); } } -void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset) +void Mesh::pack_patches(uint *patch_data) { size_t num_faces = get_num_subd_faces(); int ngons = 0; @@ -805,53 +802,9 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui } } -void Mesh::pack_primitives(ccl::PackedBVH *pack, int object, uint visibility, PackFlags pack_flags) +PrimitiveType Mesh::primitive_type() const { - if (triangles.empty()) - return; - - const size_t num_prims = num_triangles(); - - /* Use prim_offset for indexing as it is computed per geometry type, and prim_tri_verts does not - * contain data for Hair geometries. */ - float4 *prim_tri_verts = &pack->prim_tri_verts[prim_offset * 3]; - // 'pack->prim_time' is unused by Embree and OptiX - - uint type = has_motion_blur() ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE; - - /* Separate loop as other arrays are not initialized if their packing is not required. */ - if ((pack_flags & PackFlags::PACK_VISIBILITY) != 0) { - unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset]; - for (size_t k = 0; k < num_prims; ++k) { - prim_visibility[k] = visibility; - } - } - - if ((pack_flags & PackFlags::PACK_GEOMETRY) != 0) { - /* Use optix_prim_offset for indexing as those arrays also contain data for Hair geometries. */ - unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset]; - int *prim_type = &pack->prim_type[optix_prim_offset]; - int *prim_index = &pack->prim_index[optix_prim_offset]; - int *prim_object = &pack->prim_object[optix_prim_offset]; - - for (size_t k = 0; k < num_prims; ++k) { - if ((pack_flags & PackFlags::PACK_GEOMETRY) != 0) { - prim_tri_index[k] = (prim_offset + k) * 3; - prim_type[k] = type; - prim_index[k] = prim_offset + k; - prim_object[k] = object; - } - } - } - - if ((pack_flags & PackFlags::PACK_VERTICES) != 0) { - for (size_t k = 0; k < num_prims; ++k) { - const Mesh::Triangle t = get_triangle(k); - prim_tri_verts[k * 3] = float3_to_float4(verts[t.v[0]]); - prim_tri_verts[k * 3 + 1] = float3_to_float4(verts[t.v[1]]); - prim_tri_verts[k * 3 + 2] = float3_to_float4(verts[t.v[2]]); - } - } + return has_motion_blur() ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE; } CCL_NAMESPACE_END diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index e9e79f7f20d..8258c18ddd1 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -224,18 +224,10 @@ class Mesh : public Geometry { void pack_shaders(Scene *scene, uint *shader); void pack_normals(float4 *vnormal); - void pack_verts(const vector<uint> &tri_prim_index, - uint4 *tri_vindex, - uint *tri_patch, - float2 *tri_patch_uv, - size_t vert_offset, - size_t tri_offset); - void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset); - - void pack_primitives(PackedBVH *pack, - int object, - uint visibility, - PackFlags pack_flags) override; + void pack_verts(float4 *tri_verts, uint4 *tri_vindex, uint *tri_patch, float2 *tri_patch_uv); + void pack_patches(uint *patch_data); + + PrimitiveType primitive_type() const override; void tessellate(DiagSplit *split); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 1320a5eb7a6..d3ea93ca8a5 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -60,6 +60,7 @@ struct UpdateObjectTransformState { /* Packed object arrays. Those will be filled in. */ uint *object_flag; + uint *object_visibility; KernelObject *objects; Transform *object_motion_pass; DecomposedTransform *object_motion; @@ -528,6 +529,9 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s (1.0f - 0.5f * ob->shadow_terminator_shading_offset); kobject.shadow_terminator_geometry_offset = ob->shadow_terminator_geometry_offset; + kobject.visibility = ob->visibility_for_tracing(); + kobject.primitive_type = geom->primitive_type(); + /* Object flag. */ if (ob->use_holdout) { flag |= SD_OBJECT_HOLDOUT_MASK; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index ecd6946bbf8..eeb92122825 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -49,13 +49,12 @@ DeviceScene::DeviceScene(Device *device) : bvh_nodes(device, "__bvh_nodes", MEM_GLOBAL), bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_GLOBAL), object_node(device, "__object_node", MEM_GLOBAL), - prim_tri_index(device, "__prim_tri_index", MEM_GLOBAL), - prim_tri_verts(device, "__prim_tri_verts", MEM_GLOBAL), prim_type(device, "__prim_type", MEM_GLOBAL), prim_visibility(device, "__prim_visibility", MEM_GLOBAL), prim_index(device, "__prim_index", MEM_GLOBAL), prim_object(device, "__prim_object", MEM_GLOBAL), prim_time(device, "__prim_time", MEM_GLOBAL), + tri_verts(device, "__tri_verts", MEM_GLOBAL), tri_shader(device, "__tri_shader", MEM_GLOBAL), tri_vnormal(device, "__tri_vnormal", MEM_GLOBAL), tri_vindex(device, "__tri_vindex", MEM_GLOBAL), @@ -63,6 +62,7 @@ DeviceScene::DeviceScene(Device *device) tri_patch_uv(device, "__tri_patch_uv", MEM_GLOBAL), curves(device, "__curves", MEM_GLOBAL), curve_keys(device, "__curve_keys", MEM_GLOBAL), + curve_segments(device, "__curve_segments", MEM_GLOBAL), patches(device, "__patches", MEM_GLOBAL), objects(device, "__objects", MEM_GLOBAL), object_motion_pass(device, "__object_motion_pass", MEM_GLOBAL), diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 8076d0dc09c..001da31e893 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -74,8 +74,6 @@ class DeviceScene { device_vector<int4> bvh_nodes; device_vector<int4> bvh_leaf_nodes; device_vector<int> object_node; - device_vector<uint> prim_tri_index; - device_vector<float4> prim_tri_verts; device_vector<int> prim_type; device_vector<uint> prim_visibility; device_vector<int> prim_index; @@ -83,14 +81,16 @@ class DeviceScene { device_vector<float2> prim_time; /* mesh */ + device_vector<float4> tri_verts; device_vector<uint> tri_shader; device_vector<float4> tri_vnormal; device_vector<uint4> tri_vindex; device_vector<uint> tri_patch; device_vector<float2> tri_patch_uv; - device_vector<float4> curves; + device_vector<KernelCurve> curves; device_vector<float4> curve_keys; + device_vector<KernelCurveSegment> curve_segments; device_vector<uint> patches; |