vk_texture_cache: Fix invalidated pointer access
The vulkan ImageView held a reference to its source image for rescale status checking. This pointer is sometimes invalidated when the texture cache slot_images container is resized. To avoid an invalid pointer dereference, the ImageView now holds a reference to the container itself.
This commit is contained in:
		| @@ -1047,7 +1047,7 @@ bool Image::ScaleDown(bool ignore) { | ||||
| } | ||||
|  | ||||
| ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, | ||||
|                      ImageId image_id_, Image& image) | ||||
|                      ImageId image_id_, Image& image, const SlotVector<Image>&) | ||||
|     : VideoCommon::ImageViewBase{info, image.info, image_id_}, views{runtime.null_image_views} { | ||||
|     const Device& device = runtime.device; | ||||
|     if (True(image.flags & ImageFlagBits::Converted)) { | ||||
|   | ||||
| @@ -36,6 +36,7 @@ using VideoCommon::ImageViewType; | ||||
| using VideoCommon::NUM_RT; | ||||
| using VideoCommon::Region2D; | ||||
| using VideoCommon::RenderTargets; | ||||
| using VideoCommon::SlotVector; | ||||
|  | ||||
| struct ImageBufferMap { | ||||
|     ~ImageBufferMap(); | ||||
| @@ -234,7 +235,8 @@ class ImageView : public VideoCommon::ImageViewBase { | ||||
|     friend Image; | ||||
|  | ||||
| public: | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&, | ||||
|                        const SlotVector<Image>&); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, | ||||
|                        const VideoCommon::ImageViewInfo&, GPUVAddr); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||||
|   | ||||
| @@ -1473,8 +1473,7 @@ bool Image::BlitScaleHelper(bool scale_up) { | ||||
| ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, | ||||
|                      ImageId image_id_, Image& image) | ||||
|     : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, | ||||
|       src_image{&image}, image_handle{image.Handle()}, | ||||
|       samples(ConvertSampleCount(image.info.num_samples)) { | ||||
|       image_handle{image.Handle()}, samples(ConvertSampleCount(image.info.num_samples)) { | ||||
|     using Shader::TextureType; | ||||
|  | ||||
|     const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); | ||||
| @@ -1557,6 +1556,12 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | ||||
|     } | ||||
| } | ||||
|  | ||||
| ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, | ||||
|                      ImageId image_id_, Image& image, const SlotVector<Image>& slot_imgs) | ||||
|     : ImageView{runtime, info, image_id_, image} { | ||||
|     slot_images = &slot_imgs; | ||||
| } | ||||
|  | ||||
| ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||||
|                      const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_) | ||||
|     : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_}, | ||||
| @@ -1613,10 +1618,12 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type, | ||||
| } | ||||
|  | ||||
| bool ImageView::IsRescaled() const noexcept { | ||||
|     if (!src_image) { | ||||
|     if (!slot_images) { | ||||
|         return false; | ||||
|     } | ||||
|     return src_image->IsRescaled(); | ||||
|     const auto& slots = *slot_images; | ||||
|     const auto& src_image = slots[image_id]; | ||||
|     return src_image.IsRescaled(); | ||||
| } | ||||
|  | ||||
| vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) { | ||||
|   | ||||
| @@ -23,6 +23,7 @@ using VideoCommon::ImageId; | ||||
| using VideoCommon::NUM_RT; | ||||
| using VideoCommon::Region2D; | ||||
| using VideoCommon::RenderTargets; | ||||
| using VideoCommon::SlotVector; | ||||
| using VideoCore::Surface::PixelFormat; | ||||
|  | ||||
| class ASTCDecoderPass; | ||||
| @@ -170,6 +171,8 @@ private: | ||||
| class ImageView : public VideoCommon::ImageViewBase { | ||||
| public: | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&, | ||||
|                        const SlotVector<Image>&); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, | ||||
|                        const VideoCommon::ImageViewInfo&, GPUVAddr); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); | ||||
| @@ -226,7 +229,7 @@ private: | ||||
|     [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); | ||||
|  | ||||
|     const Device* device = nullptr; | ||||
|     const Image* src_image{}; | ||||
|     const SlotVector<Image>* slot_images = nullptr; | ||||
|  | ||||
|     std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views; | ||||
|     std::unique_ptr<StorageViews> storage_views; | ||||
|   | ||||
| @@ -1397,7 +1397,8 @@ ImageViewId TextureCache<P>::FindOrEmplaceImageView(ImageId image_id, const Imag | ||||
|     if (const ImageViewId image_view_id = image.FindView(info); image_view_id) { | ||||
|         return image_view_id; | ||||
|     } | ||||
|     const ImageViewId image_view_id = slot_image_views.insert(runtime, info, image_id, image); | ||||
|     const ImageViewId image_view_id = | ||||
|         slot_image_views.insert(runtime, info, image_id, image, slot_images); | ||||
|     image.InsertView(info, image_view_id); | ||||
|     return image_view_id; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user