@@ -651,6 +651,14 @@ struct DeviceShared {
651651 render_passes : Mutex < FastHashMap < RenderPassKey , vk:: RenderPass > > ,
652652 sampler_cache : Mutex < sampler:: SamplerCache > ,
653653 memory_allocations_counter : InternalCounter ,
654+
655+ /// Because we have cached framebuffers which are not deleted from until
656+ /// the device is destroyed, if the implementation of vulkan re-uses handles
657+ /// we need some way to differentiate between the old handle and the new handle.
658+ /// This factory allows us to have a dedicated identity value for each texture.
659+ texture_identity_factory : ResourceIdentityFactory < vk:: Image > ,
660+ /// As above, for texture views.
661+ texture_view_identity_factory : ResourceIdentityFactory < vk:: ImageView > ,
654662}
655663
656664impl Drop for DeviceShared {
@@ -864,6 +872,7 @@ pub struct Texture {
864872 block : Option < gpu_alloc:: MemoryBlock < vk:: DeviceMemory > > ,
865873 format : wgt:: TextureFormat ,
866874 copy_size : crate :: CopyExtent ,
875+ identity : ResourceIdentity < vk:: Image > ,
867876}
868877
869878impl crate :: DynTexture for Texture { }
@@ -886,6 +895,8 @@ pub struct TextureView {
886895 raw_format : vk:: Format ,
887896 base_mip_level : u32 ,
888897 dimension : wgt:: TextureViewDimension ,
898+ texture_identity : ResourceIdentity < vk:: Image > ,
899+ view_identity : ResourceIdentity < vk:: ImageView > ,
889900}
890901
891902impl crate :: DynTextureView for TextureView { }
@@ -897,6 +908,14 @@ impl TextureView {
897908 pub unsafe fn raw_handle ( & self ) -> vk:: ImageView {
898909 self . raw
899910 }
911+
912+ /// Returns the raw texture view, along with its identity.
913+ fn identified_raw_view ( & self ) -> IdentifiedTextureView {
914+ IdentifiedTextureView {
915+ raw : self . raw ,
916+ identity : self . view_identity ,
917+ }
918+ }
900919}
901920
902921#[ derive( Debug ) ]
@@ -956,16 +975,97 @@ impl Temp {
956975 }
957976}
958977
978+ /// Generates unique IDs for each resource of type `T`.
979+ ///
980+ /// Because vk handles are not permanently unique, this
981+ /// provides a way to generate unique IDs for each resource.
982+ struct ResourceIdentityFactory < T > {
983+ #[ cfg( not( target_has_atomic = "64" ) ) ]
984+ next_id : Mutex < u64 > ,
985+ #[ cfg( target_has_atomic = "64" ) ]
986+ next_id : core:: sync:: atomic:: AtomicU64 ,
987+ _phantom : PhantomData < T > ,
988+ }
989+
990+ impl < T > ResourceIdentityFactory < T > {
991+ fn new ( ) -> Self {
992+ Self {
993+ #[ cfg( not( target_has_atomic = "64" ) ) ]
994+ next_id : Mutex :: new ( 0 ) ,
995+ #[ cfg( target_has_atomic = "64" ) ]
996+ next_id : core:: sync:: atomic:: AtomicU64 :: new ( 0 ) ,
997+ _phantom : PhantomData ,
998+ }
999+ }
1000+
1001+ /// Returns a new unique ID for a resource of type `T`.
1002+ fn next ( & self ) -> ResourceIdentity < T > {
1003+ #[ cfg( not( target_has_atomic = "64" ) ) ]
1004+ {
1005+ let mut next_id = self . next_id . lock ( ) ;
1006+ let id = * next_id;
1007+ * next_id += 1 ;
1008+ ResourceIdentity {
1009+ id,
1010+ _phantom : PhantomData ,
1011+ }
1012+ }
1013+
1014+ #[ cfg( target_has_atomic = "64" ) ]
1015+ ResourceIdentity {
1016+ id : self
1017+ . next_id
1018+ . fetch_add ( 1 , core:: sync:: atomic:: Ordering :: Relaxed ) ,
1019+ _phantom : PhantomData ,
1020+ }
1021+ }
1022+ }
1023+
1024+ /// A unique identifier for a resource of type `T`.
1025+ ///
1026+ /// This is used as a hashable key for resources, which
1027+ /// is permanently unique through the lifetime of the program.
1028+ #[ derive( Debug , Copy , Clone , Eq , Hash , PartialEq ) ]
1029+ struct ResourceIdentity < T > {
1030+ id : u64 ,
1031+ _phantom : PhantomData < T > ,
1032+ }
1033+
9591034#[ derive( Clone , Eq , Hash , PartialEq ) ]
9601035struct FramebufferKey {
9611036 raw_pass : vk:: RenderPass ,
962- attachments : ArrayVec < vk:: ImageView , { MAX_TOTAL_ATTACHMENTS } > ,
1037+ /// Because this is used as a key in a hash map, we need to include the identity
1038+ /// so that this hashes differently, even if the ImageView handles are the same
1039+ /// between different views.
1040+ attachment_identities : ArrayVec < ResourceIdentity < vk:: ImageView > , { MAX_TOTAL_ATTACHMENTS } > ,
1041+ /// While this is redundant for calculating the hash, we need access to an array
1042+ /// of all the raw ImageViews when we are creating the actual framebuffer,
1043+ /// so we store this here.
1044+ attachment_views : ArrayVec < vk:: ImageView , { MAX_TOTAL_ATTACHMENTS } > ,
9631045 extent : wgt:: Extent3d ,
9641046}
9651047
1048+ impl FramebufferKey {
1049+ fn push_view ( & mut self , view : IdentifiedTextureView ) {
1050+ self . attachment_identities . push ( view. identity ) ;
1051+ self . attachment_views . push ( view. raw ) ;
1052+ }
1053+ }
1054+
1055+ /// A texture view paired with its identity.
1056+ #[ derive( Copy , Clone ) ]
1057+ struct IdentifiedTextureView {
1058+ raw : vk:: ImageView ,
1059+ identity : ResourceIdentity < vk:: ImageView > ,
1060+ }
1061+
9661062#[ derive( Clone , Eq , Hash , PartialEq ) ]
9671063struct TempTextureViewKey {
9681064 texture : vk:: Image ,
1065+ /// As this is used in a hashmap, we need to
1066+ /// include the identity so that this hashes differently,
1067+ /// even if the Image handles are the same between different images.
1068+ texture_identity : ResourceIdentity < vk:: Image > ,
9691069 format : vk:: Format ,
9701070 mip_level : u32 ,
9711071 depth_slice : u32 ,
@@ -1008,7 +1108,7 @@ pub struct CommandEncoder {
10081108 end_of_pass_timer_query : Option < ( vk:: QueryPool , u32 ) > ,
10091109
10101110 framebuffers : FastHashMap < FramebufferKey , vk:: Framebuffer > ,
1011- temp_texture_views : FastHashMap < TempTextureViewKey , vk :: ImageView > ,
1111+ temp_texture_views : FastHashMap < TempTextureViewKey , IdentifiedTextureView > ,
10121112
10131113 counters : Arc < wgt:: HalCounters > ,
10141114}
@@ -1037,7 +1137,7 @@ impl Drop for CommandEncoder {
10371137 }
10381138
10391139 for ( _, view) in self . temp_texture_views . drain ( ) {
1040- unsafe { self . device . raw . destroy_image_view ( view, None ) } ;
1140+ unsafe { self . device . raw . destroy_image_view ( view. raw , None ) } ;
10411141 }
10421142
10431143 self . counters . command_encoders . sub ( 1 ) ;
0 commit comments