@@ -649,6 +649,14 @@ struct DeviceShared {
649
649
render_passes : Mutex < FastHashMap < RenderPassKey , vk:: RenderPass > > ,
650
650
sampler_cache : Mutex < sampler:: SamplerCache > ,
651
651
memory_allocations_counter : InternalCounter ,
652
+
653
+ /// Because we have cached framebuffers which are not deleted from until
654
+ /// the device is destroyed, if the implementation of vulkan re-uses handles
655
+ /// we need some way to differentiate between the old handle and the new handle.
656
+ /// This factory allows us to have a dedicated identity value for each texture.
657
+ texture_identity_factory : ResourceIdentityFactory < vk:: Image > ,
658
+ /// As above, for texture views.
659
+ texture_view_identity_factory : ResourceIdentityFactory < vk:: ImageView > ,
652
660
}
653
661
654
662
impl Drop for DeviceShared {
@@ -862,6 +870,7 @@ pub struct Texture {
862
870
block : Option < gpu_alloc:: MemoryBlock < vk:: DeviceMemory > > ,
863
871
format : wgt:: TextureFormat ,
864
872
copy_size : crate :: CopyExtent ,
873
+ identity : ResourceIdentity < vk:: Image > ,
865
874
}
866
875
867
876
impl crate :: DynTexture for Texture { }
@@ -884,6 +893,8 @@ pub struct TextureView {
884
893
raw_format : vk:: Format ,
885
894
base_mip_level : u32 ,
886
895
dimension : wgt:: TextureViewDimension ,
896
+ texture_identity : ResourceIdentity < vk:: Image > ,
897
+ view_identity : ResourceIdentity < vk:: ImageView > ,
887
898
}
888
899
889
900
impl crate :: DynTextureView for TextureView { }
@@ -895,6 +906,14 @@ impl TextureView {
895
906
pub unsafe fn raw_handle ( & self ) -> vk:: ImageView {
896
907
self . raw
897
908
}
909
+
910
+ /// Returns the raw texture view, along with its identity.
911
+ fn identified_raw_view ( & self ) -> IdentifiedTextureView {
912
+ IdentifiedTextureView {
913
+ raw : self . raw ,
914
+ identity : self . view_identity ,
915
+ }
916
+ }
898
917
}
899
918
900
919
#[ derive( Debug ) ]
@@ -954,16 +973,97 @@ impl Temp {
954
973
}
955
974
}
956
975
976
+ /// Generates unique IDs for each resource of type `T`.
977
+ ///
978
+ /// Because vk handles are not permanently unique, this
979
+ /// provides a way to generate unique IDs for each resource.
980
+ struct ResourceIdentityFactory < T > {
981
+ #[ cfg( not( target_has_atomic = "64" ) ) ]
982
+ next_id : Mutex < u64 > ,
983
+ #[ cfg( target_has_atomic = "64" ) ]
984
+ next_id : core:: sync:: atomic:: AtomicU64 ,
985
+ _phantom : PhantomData < T > ,
986
+ }
987
+
988
+ impl < T > ResourceIdentityFactory < T > {
989
+ fn new ( ) -> Self {
990
+ Self {
991
+ #[ cfg( not( target_has_atomic = "64" ) ) ]
992
+ next_id : Mutex :: new ( 0 ) ,
993
+ #[ cfg( target_has_atomic = "64" ) ]
994
+ next_id : core:: sync:: atomic:: AtomicU64 :: new ( 0 ) ,
995
+ _phantom : PhantomData ,
996
+ }
997
+ }
998
+
999
+ /// Returns a new unique ID for a resource of type `T`.
1000
+ fn next ( & self ) -> ResourceIdentity < T > {
1001
+ #[ cfg( not( target_has_atomic = "64" ) ) ]
1002
+ {
1003
+ let mut next_id = self . next_id . lock ( ) ;
1004
+ let id = * next_id;
1005
+ * next_id += 1 ;
1006
+ ResourceIdentity {
1007
+ id,
1008
+ _phantom : PhantomData ,
1009
+ }
1010
+ }
1011
+
1012
+ #[ cfg( target_has_atomic = "64" ) ]
1013
+ ResourceIdentity {
1014
+ id : self
1015
+ . next_id
1016
+ . fetch_add ( 1 , core:: sync:: atomic:: Ordering :: Relaxed ) ,
1017
+ _phantom : PhantomData ,
1018
+ }
1019
+ }
1020
+ }
1021
+
1022
+ /// A unique identifier for a resource of type `T`.
1023
+ ///
1024
+ /// This is used as a hashable key for resources, which
1025
+ /// is permanently unique through the lifetime of the program.
1026
+ #[ derive( Debug , Copy , Clone , Eq , Hash , PartialEq ) ]
1027
+ struct ResourceIdentity < T > {
1028
+ id : u64 ,
1029
+ _phantom : PhantomData < T > ,
1030
+ }
1031
+
957
1032
#[ derive( Clone , Eq , Hash , PartialEq ) ]
958
1033
struct FramebufferKey {
959
1034
raw_pass : vk:: RenderPass ,
960
- attachments : ArrayVec < vk:: ImageView , { MAX_TOTAL_ATTACHMENTS } > ,
1035
+ /// Because this is used as a key in a hash map, we need to include the identity
1036
+ /// so that this hashes differently, even if the ImageView handles are the same
1037
+ /// between different views.
1038
+ attachment_identities : ArrayVec < ResourceIdentity < vk:: ImageView > , { MAX_TOTAL_ATTACHMENTS } > ,
1039
+ /// While this is redundant for calculating the hash, we need access to an array
1040
+ /// of all the raw ImageViews when we are creating the actual framebuffer,
1041
+ /// so we store this here.
1042
+ attachment_views : ArrayVec < vk:: ImageView , { MAX_TOTAL_ATTACHMENTS } > ,
961
1043
extent : wgt:: Extent3d ,
962
1044
}
963
1045
1046
+ impl FramebufferKey {
1047
+ fn push_view ( & mut self , view : IdentifiedTextureView ) {
1048
+ self . attachment_identities . push ( view. identity ) ;
1049
+ self . attachment_views . push ( view. raw ) ;
1050
+ }
1051
+ }
1052
+
1053
+ /// A texture view paired with its identity.
1054
+ #[ derive( Copy , Clone ) ]
1055
+ struct IdentifiedTextureView {
1056
+ raw : vk:: ImageView ,
1057
+ identity : ResourceIdentity < vk:: ImageView > ,
1058
+ }
1059
+
964
1060
#[ derive( Clone , Eq , Hash , PartialEq ) ]
965
1061
struct TempTextureViewKey {
966
1062
texture : vk:: Image ,
1063
+ /// As this is used in a hashmap, we need to
1064
+ /// include the identity so that this hashes differently,
1065
+ /// even if the Image handles are the same between different images.
1066
+ texture_identity : ResourceIdentity < vk:: Image > ,
967
1067
format : vk:: Format ,
968
1068
mip_level : u32 ,
969
1069
depth_slice : u32 ,
@@ -1006,7 +1106,7 @@ pub struct CommandEncoder {
1006
1106
end_of_pass_timer_query : Option < ( vk:: QueryPool , u32 ) > ,
1007
1107
1008
1108
framebuffers : FastHashMap < FramebufferKey , vk:: Framebuffer > ,
1009
- temp_texture_views : FastHashMap < TempTextureViewKey , vk :: ImageView > ,
1109
+ temp_texture_views : FastHashMap < TempTextureViewKey , IdentifiedTextureView > ,
1010
1110
1011
1111
counters : Arc < wgt:: HalCounters > ,
1012
1112
}
@@ -1035,7 +1135,7 @@ impl Drop for CommandEncoder {
1035
1135
}
1036
1136
1037
1137
for ( _, view) in self . temp_texture_views . drain ( ) {
1038
- unsafe { self . device . raw . destroy_image_view ( view, None ) } ;
1138
+ unsafe { self . device . raw . destroy_image_view ( view. raw , None ) } ;
1039
1139
}
1040
1140
1041
1141
self . counters . command_encoders . sub ( 1 ) ;
0 commit comments