diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index c3050887cf..0ba56ff1e1 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1344,7 +1344,6 @@ bool Image::ScaleUp(bool ignore) {
         return false;
     }
     has_scaled = true;
-    const auto& device = runtime->device;
     if (!scaled_image) {
         const bool is_2d = info.type == ImageType::e2D;
         const u32 scaled_width = resolution.ScaleUp(info.size.width);
@@ -1352,7 +1351,7 @@ bool Image::ScaleUp(bool ignore) {
         auto scaled_info = info;
         scaled_info.size.width = scaled_width;
         scaled_info.size.height = scaled_height;
-        scaled_image = MakeImage(device, scaled_info);
+        scaled_image = MakeImage(runtime->device, scaled_info);
         auto& allocator = runtime->memory_allocator;
         scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal));
         ignore = false;
@@ -1361,18 +1360,13 @@ bool Image::ScaleUp(bool ignore) {
     if (ignore) {
         return true;
     }
-
     if (aspect_mask == 0) {
         aspect_mask = ImageAspectMask(info.format);
     }
-    static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal;
-    const PixelFormat format = StorageFormat(info.format);
-    const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format;
-    const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
-    if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) {
-        BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution);
-    } else {
+    if (NeedsScaleHelper()) {
         return BlitScaleHelper(true);
+    } else {
+        BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution);
     }
     return true;
 }
@@ -1394,15 +1388,10 @@ bool Image::ScaleDown(bool ignore) {
     if (aspect_mask == 0) {
         aspect_mask = ImageAspectMask(info.format);
     }
-    static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal;
-    const PixelFormat format = StorageFormat(info.format);
-    const auto& device = runtime->device;
-    const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format;
-    const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
-    if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) {
-        BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false);
-    } else {
+    if (NeedsScaleHelper()) {
         return BlitScaleHelper(false);
+    } else {
+        BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false);
     }
     return true;
 }
@@ -1470,6 +1459,20 @@ bool Image::BlitScaleHelper(bool scale_up) {
     return true;
 }
 
+bool Image::NeedsScaleHelper() const {
+    const auto& device = runtime->device;
+    const bool needs_msaa_helper = info.num_samples > 1 && device.CantBlitMSAA();
+    if (needs_msaa_helper) {
+        return true;
+    }
+    static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal;
+    const PixelFormat format = StorageFormat(info.format);
+    const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format;
+    const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
+    const bool needs_blit_helper = !device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT);
+    return needs_blit_helper;
+}
+
 ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
                      ImageId image_id_, Image& image)
     : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 2f12be78b3..c81130dd20 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -149,6 +149,8 @@ public:
 private:
     bool BlitScaleHelper(bool scale_up);
 
+    bool NeedsScaleHelper() const;
+
     VKScheduler* scheduler{};
     TextureCacheRuntime* runtime{};
 
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 9862b815b9..3d78efddce 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -638,15 +638,20 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
         }
     }
 
-    if (ext_vertex_input_dynamic_state && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) {
+    const bool is_intel_windows = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS;
+    if (ext_vertex_input_dynamic_state && is_intel_windows) {
         LOG_WARNING(Render_Vulkan, "Blacklisting Intel for VK_EXT_vertex_input_dynamic_state");
         ext_vertex_input_dynamic_state = false;
     }
-    if (is_float16_supported && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) {
+    if (is_float16_supported && is_intel_windows) {
         // Intel's compiler crashes when using fp16 on Astral Chain, disable it for the time being.
         LOG_WARNING(Render_Vulkan, "Blacklisting Intel proprietary from float16 math");
         is_float16_supported = false;
     }
+    if (is_intel_windows) {
+        LOG_WARNING(Render_Vulkan, "Intel proprietary drivers do not support MSAA image blits");
+        cant_blit_msaa = true;
+    }
 
     supports_d24_depth =
         IsFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT,
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 4c9d86aad1..37d140ebdd 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -350,6 +350,10 @@ public:
         return supports_d24_depth;
     }
 
+    bool CantBlitMSAA() const {
+        return cant_blit_msaa;
+    }
+
 private:
     /// Checks if the physical device is suitable.
     void CheckSuitability(bool requires_swapchain) const;
@@ -443,6 +447,7 @@ private:
     bool has_renderdoc{};                   ///< Has RenderDoc attached
     bool has_nsight_graphics{};             ///< Has Nsight Graphics attached
     bool supports_d24_depth{};              ///< Supports D24 depth buffers.
+    bool cant_blit_msaa{};                  ///< Does not support MSAA<->MSAA blitting.
 
     // Telemetry parameters
     std::string vendor_name;                       ///< Device's driver name.