1
1
use crate :: {
2
2
mesh:: { InnerMeshVertexBufferLayout , MeshVertexBufferLayout } ,
3
- render_resource:: { CachedPipelineId , RenderPipelineCache , RenderPipelineDescriptor } ,
3
+ render_resource:: {
4
+ CachedPipelineId , RenderPipelineCache , RenderPipelineDescriptor , VertexBufferLayout ,
5
+ } ,
6
+ } ;
7
+ use bevy_utils:: {
8
+ hashbrown:: hash_map:: RawEntryMut , Entry , HashMap , Hashed , PreHashMap , PreHashMapExt ,
4
9
} ;
5
- use bevy_utils:: { HashMap , PreHashMap , PreHashMapExt } ;
6
10
use std:: hash:: Hash ;
7
11
8
12
pub struct SpecializedPipelines < S : SpecializedPipeline > {
@@ -37,13 +41,15 @@ pub trait SpecializedPipeline {
37
41
}
38
42
39
43
pub struct SpecializedMeshPipelines < S : SpecializedMeshPipeline > {
40
- cache : PreHashMap < InnerMeshVertexBufferLayout , HashMap < S :: Key , CachedPipelineId > > ,
44
+ mesh_layout_cache : PreHashMap < InnerMeshVertexBufferLayout , HashMap < S :: Key , CachedPipelineId > > ,
45
+ vertex_layout_cache : HashMap < VertexBufferLayout , HashMap < S :: Key , CachedPipelineId > > ,
41
46
}
42
47
43
48
impl < S : SpecializedMeshPipeline > Default for SpecializedMeshPipelines < S > {
44
49
fn default ( ) -> Self {
45
50
Self {
46
- cache : Default :: default ( ) ,
51
+ mesh_layout_cache : Default :: default ( ) ,
52
+ vertex_layout_cache : Default :: default ( ) ,
47
53
}
48
54
}
49
55
}
@@ -57,10 +63,29 @@ impl<S: SpecializedMeshPipeline> SpecializedMeshPipelines<S> {
57
63
key : S :: Key ,
58
64
layout : & MeshVertexBufferLayout ,
59
65
) -> CachedPipelineId {
60
- let map = self . cache . get_or_insert_with ( layout, Default :: default) ;
66
+ let map = self
67
+ . mesh_layout_cache
68
+ . get_or_insert_with ( layout, Default :: default) ;
61
69
* map. entry ( key. clone ( ) ) . or_insert_with ( || {
62
- let descriptor = specialize_pipeline. specialize ( key, layout) ;
63
- cache. queue ( descriptor)
70
+ let descriptor = specialize_pipeline. specialize ( key. clone ( ) , layout) ;
71
+ // Different MeshVertexBufferLayouts can produce the same final VertexBufferLayout
72
+ // We want compatible vertex buffer layouts to use the same pipelines, so we must "deduplicate" them
73
+ let layout_map = match self
74
+ . vertex_layout_cache
75
+ . raw_entry_mut ( )
76
+ . from_key ( & descriptor. vertex . buffers [ 0 ] )
77
+ {
78
+ RawEntryMut :: Occupied ( entry) => entry. into_mut ( ) ,
79
+ RawEntryMut :: Vacant ( entry) => {
80
+ entry
81
+ . insert ( descriptor. vertex . buffers [ 0 ] . clone ( ) , Default :: default ( ) )
82
+ . 1
83
+ }
84
+ } ;
85
+ match layout_map. entry ( key) {
86
+ Entry :: Occupied ( entry) => * entry. into_mut ( ) ,
87
+ Entry :: Vacant ( entry) => * entry. insert ( cache. queue ( descriptor) ) ,
88
+ }
64
89
} )
65
90
}
66
91
}
0 commit comments