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:
ameerj 2021-12-23 20:55:48 -05:00
parent 516325eba8
commit 481b210c0d
5 changed files with 21 additions and 8 deletions

View file

@ -1047,7 +1047,7 @@ bool Image::ScaleDown(bool ignore) {
} }
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, 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} { : VideoCommon::ImageViewBase{info, image.info, image_id_}, views{runtime.null_image_views} {
const Device& device = runtime.device; const Device& device = runtime.device;
if (True(image.flags & ImageFlagBits::Converted)) { if (True(image.flags & ImageFlagBits::Converted)) {

View file

@ -36,6 +36,7 @@ using VideoCommon::ImageViewType;
using VideoCommon::NUM_RT; using VideoCommon::NUM_RT;
using VideoCommon::Region2D; using VideoCommon::Region2D;
using VideoCommon::RenderTargets; using VideoCommon::RenderTargets;
using VideoCommon::SlotVector;
struct ImageBufferMap { struct ImageBufferMap {
~ImageBufferMap(); ~ImageBufferMap();
@ -234,7 +235,8 @@ class ImageView : public VideoCommon::ImageViewBase {
friend Image; friend Image;
public: 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&, explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
const VideoCommon::ImageViewInfo&, GPUVAddr); const VideoCommon::ImageViewInfo&, GPUVAddr);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,

View file

@ -1473,8 +1473,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image) ImageId image_id_, Image& image)
: VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
src_image{&image}, image_handle{image.Handle()}, image_handle{image.Handle()}, samples(ConvertSampleCount(image.info.num_samples)) {
samples(ConvertSampleCount(image.info.num_samples)) {
using Shader::TextureType; using Shader::TextureType;
const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); 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, ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_) const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_)
: VideoCommon::ImageViewBase{info, view_info}, gpu_addr{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 { bool ImageView::IsRescaled() const noexcept {
if (!src_image) { if (!slot_images) {
return false; 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) { vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {

View file

@ -23,6 +23,7 @@ using VideoCommon::ImageId;
using VideoCommon::NUM_RT; using VideoCommon::NUM_RT;
using VideoCommon::Region2D; using VideoCommon::Region2D;
using VideoCommon::RenderTargets; using VideoCommon::RenderTargets;
using VideoCommon::SlotVector;
using VideoCore::Surface::PixelFormat; using VideoCore::Surface::PixelFormat;
class ASTCDecoderPass; class ASTCDecoderPass;
@ -170,6 +171,8 @@ private:
class ImageView : public VideoCommon::ImageViewBase { class ImageView : public VideoCommon::ImageViewBase {
public: public:
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); 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&, explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
const VideoCommon::ImageViewInfo&, GPUVAddr); const VideoCommon::ImageViewInfo&, GPUVAddr);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&);
@ -226,7 +229,7 @@ private:
[[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
const Device* device = nullptr; 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::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
std::unique_ptr<StorageViews> storage_views; std::unique_ptr<StorageViews> storage_views;

View file

@ -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) { if (const ImageViewId image_view_id = image.FindView(info); image_view_id) {
return 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); image.InsertView(info, image_view_id);
return image_view_id; return image_view_id;
} }