Browse Source

Optimize base and shadow meshes for cache

Previously, vertex cache optimization was ran for the LOD meshes, but
was never ran for the base mesh or for the shadow meshes, including
shadow LOD chain (shadow LOD chain would sometimes get implicitly
optimized for vertex cache as a byproduct of base LOD optimization, but
not always). This could significantly affect the rendering performance
of geometry heavy scenes, especially for depth or shadow passes where
the fragment load is light.
Arseny Kapoulkine 1 year ago
parent
commit
0fde03c0e0

+ 2 - 0
editor/import/3d/resource_importer_scene.cpp

@@ -2544,6 +2544,8 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_
 					}
 					}
 				}
 				}
 
 
+				src_mesh_node->get_mesh()->optimize_indices_for_cache();
+
 				if (generate_lods) {
 				if (generate_lods) {
 					Array skin_pose_transform_array = _get_skinned_pose_transforms(src_mesh_node);
 					Array skin_pose_transform_array = _get_skinned_pose_transforms(src_mesh_node);
 					src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle, skin_pose_transform_array, raycast_normals);
 					src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle, skin_pose_transform_array, raycast_normals);

+ 35 - 0
scene/resources/3d/importer_mesh.cpp

@@ -256,6 +256,33 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma
 	mesh.unref();
 	mesh.unref();
 }
 }
 
 
+void ImporterMesh::optimize_indices_for_cache() {
+	if (!SurfaceTool::optimize_vertex_cache_func) {
+		return;
+	}
+
+	for (int i = 0; i < surfaces.size(); i++) {
+		if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) {
+			continue;
+		}
+
+		Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX];
+		PackedInt32Array indices = surfaces[i].arrays[RS::ARRAY_INDEX];
+
+		unsigned int index_count = indices.size();
+		unsigned int vertex_count = vertices.size();
+
+		if (index_count == 0) {
+			continue;
+		}
+
+		int *indices_ptr = indices.ptrw();
+		SurfaceTool::optimize_vertex_cache_func((unsigned int *)indices_ptr, (const unsigned int *)indices_ptr, index_count, vertex_count);
+
+		surfaces.write[i].arrays[RS::ARRAY_INDEX] = indices;
+	}
+}
+
 #define VERTEX_SKIN_FUNC(bone_count, vert_idx, read_array, write_array, transform_array, bone_array, weight_array) \
 #define VERTEX_SKIN_FUNC(bone_count, vert_idx, read_array, write_array, transform_array, bone_array, weight_array) \
 	Vector3 transformed_vert;                                                                                      \
 	Vector3 transformed_vert;                                                                                      \
 	for (unsigned int weight_idx = 0; weight_idx < bone_count; weight_idx++) {                                     \
 	for (unsigned int weight_idx = 0; weight_idx < bone_count; weight_idx++) {                                     \
@@ -822,6 +849,10 @@ void ImporterMesh::create_shadow_mesh() {
 				index_wptr[j] = vertex_remap[index];
 				index_wptr[j] = vertex_remap[index];
 			}
 			}
 
 
+			if (SurfaceTool::optimize_vertex_cache_func) {
+				SurfaceTool::optimize_vertex_cache_func((unsigned int *)index_wptr, (const unsigned int *)index_wptr, index_count, new_vertices.size());
+			}
+
 			new_surface[RS::ARRAY_INDEX] = new_indices;
 			new_surface[RS::ARRAY_INDEX] = new_indices;
 
 
 			// Make sure the same LODs as the full version are used.
 			// Make sure the same LODs as the full version are used.
@@ -840,6 +871,10 @@ void ImporterMesh::create_shadow_mesh() {
 					index_wptr[k] = vertex_remap[index];
 					index_wptr[k] = vertex_remap[index];
 				}
 				}
 
 
+				if (SurfaceTool::optimize_vertex_cache_func) {
+					SurfaceTool::optimize_vertex_cache_func((unsigned int *)index_wptr, (const unsigned int *)index_wptr, index_count, new_vertices.size());
+				}
+
 				lods[surfaces[i].lods[j].distance] = new_indices;
 				lods[surfaces[i].lods[j].distance] = new_indices;
 			}
 			}
 		}
 		}

+ 2 - 0
scene/resources/3d/importer_mesh.h

@@ -114,6 +114,8 @@ public:
 
 
 	void set_surface_material(int p_surface, const Ref<Material> &p_material);
 	void set_surface_material(int p_surface, const Ref<Material> &p_material);
 
 
+	void optimize_indices_for_cache();
+
 	void generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array, bool p_raycast_normals = false);
 	void generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array, bool p_raycast_normals = false);
 
 
 	void create_shadow_mesh();
 	void create_shadow_mesh();