From 7342d463b8b7eb32a1392e23b014d214284c4ed7 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Tue, 13 Apr 2021 03:31:29 +0000 Subject: [PATCH] Use a sorted Map for vertex buffer attributes (#1796) The `VertexBufferLayout` returned by `crates\bevy_render\src\mesh\mesh.rs:308` was unstable, because `HashMap.iter()` has a random order. This caused the pipeline_compiler to wrongly consider a specialization to be different (`crates\bevy_render\src\pipeline\pipeline_compiler.rs:123`), causing each mesh changed event to potentially result in a different `PipelineSpecialization`. This in turn caused `Draw` to emit a `set_pipeline` much more often than needed. This fix shaves off a `BindPipeline` and two `BindDescriptorSets` (for the Camera and for global renderresources) for every mesh after the first that can now use the same specialization, where it didn't before (which was random). `StableHashMap` was not a good replacement, because it isn't `Clone`, so instead I replaced it with a `BTreeMap` which is OK in this instance, because there shouldn't be many insertions on `Mesh.attributes` after the mesh is created. --- crates/bevy_render/src/mesh/mesh.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index aece088918..83117f613b 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -13,7 +13,7 @@ use bevy_ecs::{ }; use bevy_math::*; use bevy_reflect::TypeUuid; -use std::borrow::Cow; +use std::{borrow::Cow, collections::BTreeMap}; use crate::pipeline::{InputStepMode, VertexAttribute, VertexBufferLayout}; use bevy_utils::{HashMap, HashSet}; @@ -208,9 +208,11 @@ impl From<&Indices> for IndexFormat { #[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"] pub struct Mesh { primitive_topology: PrimitiveTopology, - /// `bevy_utils::HashMap` with all defined vertex attributes (Positions, Normals, ...) for this + /// `std::collections::BTreeMap` with all defined vertex attributes (Positions, Normals, ...) for this /// mesh. Attribute name maps to attribute values. - attributes: HashMap, VertexAttributeValues>, + /// Uses a BTreeMap because, unlike HashMap, it has a defined iteration order, + /// which allows easy stable VertexBuffers (i.e. same buffer order) + attributes: BTreeMap, VertexAttributeValues>, indices: Option, }