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.
This commit is contained in:
Arseny Kapoulkine 2024-07-11 15:44:30 -07:00
parent 96be44c0ec
commit 0fde03c0e0
3 changed files with 39 additions and 0 deletions

View file

@ -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) {
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);

View file

@ -256,6 +256,33 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma
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) \
Vector3 transformed_vert; \
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];
}
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;
// 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];
}
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;
}
}

View file

@ -114,6 +114,8 @@ public:
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 create_shadow_mesh();