Skip to content

Commit

Permalink
Optimize base and shadow meshes for cache
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
zeux committed Jul 11, 2024
1 parent 26d1577 commit a6db472
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
2 changes: 2 additions & 0 deletions editor/import/3d/resource_importer_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2534,6 +2534,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);
Expand Down
35 changes: 35 additions & 0 deletions scene/resources/3d/importer_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++) { \
Expand Down Expand Up @@ -808,6 +835,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.
Expand All @@ -826,6 +857,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;
}
}
Expand Down
2 changes: 2 additions & 0 deletions scene/resources/3d/importer_mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ class ImporterMesh : public Resource {

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

void create_shadow_mesh();
Expand Down

0 comments on commit a6db472

Please sign in to comment.