diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 149e621f9c..2eaded242d 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -200,6 +200,7 @@ void RestoreGlobalState(bool is_powered_on) {
     values.use_asynchronous_shaders.SetGlobal(true);
     values.use_fast_gpu_time.SetGlobal(true);
     values.use_pessimistic_flushes.SetGlobal(true);
+    values.use_vulkan_driver_pipeline_cache.SetGlobal(true);
     values.bg_red.SetGlobal(true);
     values.bg_green.SetGlobal(true);
     values.bg_blue.SetGlobal(true);
diff --git a/src/common/settings.h b/src/common/settings.h
index 5017951c53..d9e82087d4 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -451,6 +451,8 @@ struct Values {
     SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
     SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
     SwitchableSetting<bool> use_pessimistic_flushes{false, "use_pessimistic_flushes"};
+    SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true,
+                                                             "use_vulkan_driver_pipeline_cache"};
 
     SwitchableSetting<u8> bg_red{0, "bg_red"};
     SwitchableSetting<u8> bg_green{0, "bg_green"};
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 04a3a861ef..2a0f0dbf03 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -24,13 +24,15 @@ using Shader::ImageBufferDescriptor;
 using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
 using Tegra::Texture::TexturePair;
 
-ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool,
+ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipeline_cache_,
+                                 DescriptorPool& descriptor_pool,
                                  UpdateDescriptorQueue& update_descriptor_queue_,
                                  Common::ThreadWorker* thread_worker,
                                  PipelineStatistics* pipeline_statistics,
                                  VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_,
                                  vk::ShaderModule spv_module_)
-    : device{device_}, update_descriptor_queue{update_descriptor_queue_}, info{info_},
+    : device{device_}, pipeline_cache(pipeline_cache_),
+      update_descriptor_queue{update_descriptor_queue_}, info{info_},
       spv_module(std::move(spv_module_)) {
     if (shader_notify) {
         shader_notify->MarkShaderBuilding();
@@ -56,23 +58,27 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript
         if (device.IsKhrPipelineExecutablePropertiesEnabled()) {
             flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
         }
-        pipeline = device.GetLogical().CreateComputePipeline({
-            .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
-            .pNext = nullptr,
-            .flags = flags,
-            .stage{
-                .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
-                .pNext = device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr,
-                .flags = 0,
-                .stage = VK_SHADER_STAGE_COMPUTE_BIT,
-                .module = *spv_module,
-                .pName = "main",
-                .pSpecializationInfo = nullptr,
+        pipeline = device.GetLogical().CreateComputePipeline(
+            {
+                .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+                .pNext = nullptr,
+                .flags = flags,
+                .stage{
+                    .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+                    .pNext =
+                        device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr,
+                    .flags = 0,
+                    .stage = VK_SHADER_STAGE_COMPUTE_BIT,
+                    .module = *spv_module,
+                    .pName = "main",
+                    .pSpecializationInfo = nullptr,
+                },
+                .layout = *pipeline_layout,
+                .basePipelineHandle = 0,
+                .basePipelineIndex = 0,
             },
-            .layout = *pipeline_layout,
-            .basePipelineHandle = 0,
-            .basePipelineIndex = 0,
-        });
+            *pipeline_cache);
+
         if (pipeline_statistics) {
             pipeline_statistics->Collect(*pipeline);
         }
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index d70837fc59..78d77027f9 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -28,7 +28,8 @@ class Scheduler;
 
 class ComputePipeline {
 public:
-    explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool,
+    explicit ComputePipeline(const Device& device, vk::PipelineCache& pipeline_cache,
+                             DescriptorPool& descriptor_pool,
                              UpdateDescriptorQueue& update_descriptor_queue,
                              Common::ThreadWorker* thread_worker,
                              PipelineStatistics* pipeline_statistics,
@@ -46,6 +47,7 @@ public:
 
 private:
     const Device& device;
+    vk::PipelineCache& pipeline_cache;
     UpdateDescriptorQueue& update_descriptor_queue;
     Shader::Info info;
 
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 734c379b99..f91bb5a1d7 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -234,13 +234,14 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m
 
 GraphicsPipeline::GraphicsPipeline(
     Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_,
-    VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool,
+    vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify,
+    const Device& device_, DescriptorPool& descriptor_pool,
     UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread,
     PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
     const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages,
     const std::array<const Shader::Info*, NUM_STAGES>& infos)
-    : key{key_}, device{device_}, texture_cache{texture_cache_},
-      buffer_cache{buffer_cache_}, scheduler{scheduler_},
+    : key{key_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
+      pipeline_cache(pipeline_cache_), scheduler{scheduler_},
       update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} {
     if (shader_notify) {
         shader_notify->MarkShaderBuilding();
@@ -897,27 +898,29 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
     if (device.IsKhrPipelineExecutablePropertiesEnabled()) {
         flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
     }
-    pipeline = device.GetLogical().CreateGraphicsPipeline({
-        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = flags,
-        .stageCount = static_cast<u32>(shader_stages.size()),
-        .pStages = shader_stages.data(),
-        .pVertexInputState = &vertex_input_ci,
-        .pInputAssemblyState = &input_assembly_ci,
-        .pTessellationState = &tessellation_ci,
-        .pViewportState = &viewport_ci,
-        .pRasterizationState = &rasterization_ci,
-        .pMultisampleState = &multisample_ci,
-        .pDepthStencilState = &depth_stencil_ci,
-        .pColorBlendState = &color_blend_ci,
-        .pDynamicState = &dynamic_state_ci,
-        .layout = *pipeline_layout,
-        .renderPass = render_pass,
-        .subpass = 0,
-        .basePipelineHandle = nullptr,
-        .basePipelineIndex = 0,
-    });
+    pipeline = device.GetLogical().CreateGraphicsPipeline(
+        {
+            .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+            .pNext = nullptr,
+            .flags = flags,
+            .stageCount = static_cast<u32>(shader_stages.size()),
+            .pStages = shader_stages.data(),
+            .pVertexInputState = &vertex_input_ci,
+            .pInputAssemblyState = &input_assembly_ci,
+            .pTessellationState = &tessellation_ci,
+            .pViewportState = &viewport_ci,
+            .pRasterizationState = &rasterization_ci,
+            .pMultisampleState = &multisample_ci,
+            .pDepthStencilState = &depth_stencil_ci,
+            .pColorBlendState = &color_blend_ci,
+            .pDynamicState = &dynamic_state_ci,
+            .layout = *pipeline_layout,
+            .renderPass = render_pass,
+            .subpass = 0,
+            .basePipelineHandle = nullptr,
+            .basePipelineIndex = 0,
+        },
+        *pipeline_cache);
 }
 
 void GraphicsPipeline::Validate() {
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index 1ed2967bee..67c657d0e6 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -70,16 +70,14 @@ class GraphicsPipeline {
     static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
 
 public:
-    explicit GraphicsPipeline(Scheduler& scheduler, BufferCache& buffer_cache,
-                              TextureCache& texture_cache, VideoCore::ShaderNotify* shader_notify,
-                              const Device& device, DescriptorPool& descriptor_pool,
-                              UpdateDescriptorQueue& update_descriptor_queue,
-                              Common::ThreadWorker* worker_thread,
-                              PipelineStatistics* pipeline_statistics,
-                              RenderPassCache& render_pass_cache,
-                              const GraphicsPipelineCacheKey& key,
-                              std::array<vk::ShaderModule, NUM_STAGES> stages,
-                              const std::array<const Shader::Info*, NUM_STAGES>& infos);
+    explicit GraphicsPipeline(
+        Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache,
+        vk::PipelineCache& pipeline_cache, VideoCore::ShaderNotify* shader_notify,
+        const Device& device, DescriptorPool& descriptor_pool,
+        UpdateDescriptorQueue& update_descriptor_queue, Common::ThreadWorker* worker_thread,
+        PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
+        const GraphicsPipelineCacheKey& key, std::array<vk::ShaderModule, NUM_STAGES> stages,
+        const std::array<const Shader::Info*, NUM_STAGES>& infos);
 
     GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete;
     GraphicsPipeline(GraphicsPipeline&&) noexcept = delete;
@@ -133,6 +131,7 @@ private:
     const Device& device;
     TextureCache& texture_cache;
     BufferCache& buffer_cache;
+    vk::PipelineCache& pipeline_cache;
     Scheduler& scheduler;
     UpdateDescriptorQueue& update_descriptor_queue;
 
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 3046b72aba..67e5bc648c 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -55,6 +55,7 @@ using VideoCommon::GenericEnvironment;
 using VideoCommon::GraphicsEnvironment;
 
 constexpr u32 CACHE_VERSION = 10;
+constexpr std::array<char, 8> VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'};
 
 template <typename Container>
 auto MakeSpan(Container& container) {
@@ -284,6 +285,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
       render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_},
       texture_cache{texture_cache_}, shader_notify{shader_notify_},
       use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()},
+      use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()},
       workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"),
       serialization_thread(1, "VkPipelineSerialization") {
     const auto& float_control{device.FloatControlProperties()};
@@ -362,7 +364,12 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
     };
 }
 
-PipelineCache::~PipelineCache() = default;
+PipelineCache::~PipelineCache() {
+    if (use_vulkan_pipeline_cache && !vulkan_pipeline_cache_filename.empty()) {
+        SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
+                                     CACHE_VERSION);
+    }
+}
 
 GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() {
     MICROPROFILE_SCOPE(Vulkan_PipelineCache);
@@ -418,6 +425,12 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
     }
     pipeline_cache_filename = base_dir / "vulkan.bin";
 
+    if (use_vulkan_pipeline_cache) {
+        vulkan_pipeline_cache_filename = base_dir / "vulkan_pipelines.bin";
+        vulkan_pipeline_cache =
+            LoadVulkanPipelineCache(vulkan_pipeline_cache_filename, CACHE_VERSION);
+    }
+
     struct {
         std::mutex mutex;
         size_t total{};
@@ -496,6 +509,11 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
 
     workers.WaitForRequests(stop_loading);
 
+    if (use_vulkan_pipeline_cache) {
+        SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
+                                     CACHE_VERSION);
+    }
+
     if (state.statistics) {
         state.statistics->Report();
     }
@@ -616,10 +634,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
         previous_stage = &program;
     }
     Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
-    return std::make_unique<GraphicsPipeline>(scheduler, buffer_cache, texture_cache,
-                                              &shader_notify, device, descriptor_pool,
-                                              update_descriptor_queue, thread_worker, statistics,
-                                              render_pass_cache, key, std::move(modules), infos);
+    return std::make_unique<GraphicsPipeline>(
+        scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device,
+        descriptor_pool, update_descriptor_queue, thread_worker, statistics, render_pass_cache, key,
+        std::move(modules), infos);
 
 } catch (const Shader::Exception& exception) {
     LOG_ERROR(Render_Vulkan, "{}", exception.what());
@@ -689,13 +707,107 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
         spv_module.SetObjectNameEXT(name.c_str());
     }
     Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
-    return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue,
-                                             thread_worker, statistics, &shader_notify,
-                                             program.info, std::move(spv_module));
+    return std::make_unique<ComputePipeline>(device, vulkan_pipeline_cache, descriptor_pool,
+                                             update_descriptor_queue, thread_worker, statistics,
+                                             &shader_notify, program.info, std::move(spv_module));
 
 } catch (const Shader::Exception& exception) {
     LOG_ERROR(Render_Vulkan, "{}", exception.what());
     return nullptr;
 }
 
+void PipelineCache::SerializeVulkanPipelineCache(const std::filesystem::path& filename,
+                                                 const vk::PipelineCache& pipeline_cache,
+                                                 u32 cache_version) try {
+    std::ofstream file(filename, std::ios::binary);
+    file.exceptions(std::ifstream::failbit);
+    if (!file.is_open()) {
+        LOG_ERROR(Common_Filesystem, "Failed to open Vulkan driver pipeline cache file {}",
+                  Common::FS::PathToUTF8String(filename));
+        return;
+    }
+    file.write(VULKAN_CACHE_MAGIC_NUMBER.data(), VULKAN_CACHE_MAGIC_NUMBER.size())
+        .write(reinterpret_cast<const char*>(&cache_version), sizeof(cache_version));
+
+    size_t cache_size = 0;
+    std::vector<char> cache_data;
+    if (pipeline_cache) {
+        pipeline_cache.Read(&cache_size, nullptr);
+        cache_data.resize(cache_size);
+        pipeline_cache.Read(&cache_size, cache_data.data());
+    }
+    file.write(cache_data.data(), cache_size);
+
+    LOG_INFO(Render_Vulkan, "Vulkan driver pipelines cached at: {}",
+             Common::FS::PathToUTF8String(filename));
+
+} catch (const std::ios_base::failure& e) {
+    LOG_ERROR(Common_Filesystem, "{}", e.what());
+    if (!Common::FS::RemoveFile(filename)) {
+        LOG_ERROR(Common_Filesystem, "Failed to delete Vulkan driver pipeline cache file {}",
+                  Common::FS::PathToUTF8String(filename));
+    }
+}
+
+vk::PipelineCache PipelineCache::LoadVulkanPipelineCache(const std::filesystem::path& filename,
+                                                         u32 expected_cache_version) {
+    const auto create_pipeline_cache = [this](size_t data_size, const void* data) {
+        VkPipelineCacheCreateInfo pipeline_cache_ci = {
+            .sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
+            .pNext = nullptr,
+            .flags = 0,
+            .initialDataSize = data_size,
+            .pInitialData = data};
+        return device.GetLogical().CreatePipelineCache(pipeline_cache_ci);
+    };
+    try {
+        std::ifstream file(filename, std::ios::binary | std::ios::ate);
+        if (!file.is_open()) {
+            return create_pipeline_cache(0, nullptr);
+        }
+        file.exceptions(std::ifstream::failbit);
+        const auto end{file.tellg()};
+        file.seekg(0, std::ios::beg);
+
+        std::array<char, 8> magic_number;
+        u32 cache_version;
+        file.read(magic_number.data(), magic_number.size())
+            .read(reinterpret_cast<char*>(&cache_version), sizeof(cache_version));
+        if (magic_number != VULKAN_CACHE_MAGIC_NUMBER || cache_version != expected_cache_version) {
+            file.close();
+            if (Common::FS::RemoveFile(filename)) {
+                if (magic_number != VULKAN_CACHE_MAGIC_NUMBER) {
+                    LOG_ERROR(Common_Filesystem, "Invalid Vulkan driver pipeline cache file");
+                }
+                if (cache_version != expected_cache_version) {
+                    LOG_INFO(Common_Filesystem, "Deleting old Vulkan driver pipeline cache");
+                }
+            } else {
+                LOG_ERROR(Common_Filesystem,
+                          "Invalid Vulkan pipeline cache file and failed to delete it in \"{}\"",
+                          Common::FS::PathToUTF8String(filename));
+            }
+            return create_pipeline_cache(0, nullptr);
+        }
+
+        const size_t cache_size = static_cast<size_t>(end) - magic_number.size();
+        std::vector<char> cache_data(cache_size);
+        file.read(cache_data.data(), cache_size);
+
+        LOG_INFO(Render_Vulkan,
+                 "Loaded Vulkan driver pipeline cache: ", Common::FS::PathToUTF8String(filename));
+
+        return create_pipeline_cache(cache_size, cache_data.data());
+
+    } catch (const std::ios_base::failure& e) {
+        LOG_ERROR(Common_Filesystem, "{}", e.what());
+        if (!Common::FS::RemoveFile(filename)) {
+            LOG_ERROR(Common_Filesystem, "Failed to delete Vulkan driver pipeline cache file {}",
+                      Common::FS::PathToUTF8String(filename));
+        }
+
+        return create_pipeline_cache(0, nullptr);
+    }
+}
+
 } // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index b4f593ef54..5171912d72 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -135,6 +135,12 @@ private:
                                                            PipelineStatistics* statistics,
                                                            bool build_in_parallel);
 
+    void SerializeVulkanPipelineCache(const std::filesystem::path& filename,
+                                      const vk::PipelineCache& pipeline_cache, u32 cache_version);
+
+    vk::PipelineCache LoadVulkanPipelineCache(const std::filesystem::path& filename,
+                                              u32 expected_cache_version);
+
     const Device& device;
     Scheduler& scheduler;
     DescriptorPool& descriptor_pool;
@@ -144,6 +150,7 @@ private:
     TextureCache& texture_cache;
     VideoCore::ShaderNotify& shader_notify;
     bool use_asynchronous_shaders{};
+    bool use_vulkan_pipeline_cache{};
 
     GraphicsPipelineCacheKey graphics_key{};
     GraphicsPipeline* current_pipeline{};
@@ -158,6 +165,9 @@ private:
 
     std::filesystem::path pipeline_cache_filename;
 
+    std::filesystem::path vulkan_pipeline_cache_filename;
+    vk::PipelineCache vulkan_pipeline_cache;
+
     Common::ThreadWorker workers;
     Common::ThreadWorker serialization_thread;
     DynamicFeatures dynamic_features;
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 861767c136..61be1fce10 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -152,6 +152,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkCreateGraphicsPipelines);
     X(vkCreateImage);
     X(vkCreateImageView);
+    X(vkCreatePipelineCache);
     X(vkCreatePipelineLayout);
     X(vkCreateQueryPool);
     X(vkCreateRenderPass);
@@ -171,6 +172,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkDestroyImage);
     X(vkDestroyImageView);
     X(vkDestroyPipeline);
+    X(vkDestroyPipelineCache);
     X(vkDestroyPipelineLayout);
     X(vkDestroyQueryPool);
     X(vkDestroyRenderPass);
@@ -188,6 +190,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkGetEventStatus);
     X(vkGetFenceStatus);
     X(vkGetImageMemoryRequirements);
+    X(vkGetPipelineCacheData);
     X(vkGetMemoryFdKHR);
 #ifdef _WIN32
     X(vkGetMemoryWin32HandleKHR);
@@ -431,6 +434,10 @@ void Destroy(VkDevice device, VkPipeline handle, const DeviceDispatch& dld) noex
     dld.vkDestroyPipeline(device, handle, nullptr);
 }
 
+void Destroy(VkDevice device, VkPipelineCache handle, const DeviceDispatch& dld) noexcept {
+    dld.vkDestroyPipelineCache(device, handle, nullptr);
+}
+
 void Destroy(VkDevice device, VkPipelineLayout handle, const DeviceDispatch& dld) noexcept {
     dld.vkDestroyPipelineLayout(device, handle, nullptr);
 }
@@ -651,6 +658,10 @@ void ShaderModule::SetObjectNameEXT(const char* name) const {
     SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SHADER_MODULE, name);
 }
 
+void PipelineCache::SetObjectNameEXT(const char* name) const {
+    SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_PIPELINE_CACHE, name);
+}
+
 void Semaphore::SetObjectNameEXT(const char* name) const {
     SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_SEMAPHORE, name);
 }
@@ -746,21 +757,29 @@ DescriptorSetLayout Device::CreateDescriptorSetLayout(
     return DescriptorSetLayout(object, handle, *dld);
 }
 
+PipelineCache Device::CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const {
+    VkPipelineCache cache;
+    Check(dld->vkCreatePipelineCache(handle, &ci, nullptr, &cache));
+    return PipelineCache(cache, handle, *dld);
+}
+
 PipelineLayout Device::CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const {
     VkPipelineLayout object;
     Check(dld->vkCreatePipelineLayout(handle, &ci, nullptr, &object));
     return PipelineLayout(object, handle, *dld);
 }
 
-Pipeline Device::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci) const {
+Pipeline Device::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci,
+                                        VkPipelineCache cache) const {
     VkPipeline object;
-    Check(dld->vkCreateGraphicsPipelines(handle, nullptr, 1, &ci, nullptr, &object));
+    Check(dld->vkCreateGraphicsPipelines(handle, cache, 1, &ci, nullptr, &object));
     return Pipeline(object, handle, *dld);
 }
 
-Pipeline Device::CreateComputePipeline(const VkComputePipelineCreateInfo& ci) const {
+Pipeline Device::CreateComputePipeline(const VkComputePipelineCreateInfo& ci,
+                                       VkPipelineCache cache) const {
     VkPipeline object;
-    Check(dld->vkCreateComputePipelines(handle, nullptr, 1, &ci, nullptr, &object));
+    Check(dld->vkCreateComputePipelines(handle, cache, 1, &ci, nullptr, &object));
     return Pipeline(object, handle, *dld);
 }
 
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index accfad8c13..412779b51b 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -270,6 +270,7 @@ struct DeviceDispatch : InstanceDispatch {
     PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines{};
     PFN_vkCreateImage vkCreateImage{};
     PFN_vkCreateImageView vkCreateImageView{};
+    PFN_vkCreatePipelineCache vkCreatePipelineCache{};
     PFN_vkCreatePipelineLayout vkCreatePipelineLayout{};
     PFN_vkCreateQueryPool vkCreateQueryPool{};
     PFN_vkCreateRenderPass vkCreateRenderPass{};
@@ -289,6 +290,7 @@ struct DeviceDispatch : InstanceDispatch {
     PFN_vkDestroyImage vkDestroyImage{};
     PFN_vkDestroyImageView vkDestroyImageView{};
     PFN_vkDestroyPipeline vkDestroyPipeline{};
+    PFN_vkDestroyPipelineCache vkDestroyPipelineCache{};
     PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout{};
     PFN_vkDestroyQueryPool vkDestroyQueryPool{};
     PFN_vkDestroyRenderPass vkDestroyRenderPass{};
@@ -306,6 +308,7 @@ struct DeviceDispatch : InstanceDispatch {
     PFN_vkGetEventStatus vkGetEventStatus{};
     PFN_vkGetFenceStatus vkGetFenceStatus{};
     PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements{};
+    PFN_vkGetPipelineCacheData vkGetPipelineCacheData{};
     PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR{};
 #ifdef _WIN32
     PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{};
@@ -351,6 +354,7 @@ void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept;
+void Destroy(VkDevice, VkPipelineCache, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept;
@@ -773,6 +777,18 @@ public:
     void SetObjectNameEXT(const char* name) const;
 };
 
+class PipelineCache : public Handle<VkPipelineCache, VkDevice, DeviceDispatch> {
+    using Handle<VkPipelineCache, VkDevice, DeviceDispatch>::Handle;
+
+public:
+    /// Set object name.
+    void SetObjectNameEXT(const char* name) const;
+
+    VkResult Read(size_t* size, void* data) const noexcept {
+        return dld->vkGetPipelineCacheData(owner, handle, size, data);
+    }
+};
+
 class Semaphore : public Handle<VkSemaphore, VkDevice, DeviceDispatch> {
     using Handle<VkSemaphore, VkDevice, DeviceDispatch>::Handle;
 
@@ -844,11 +860,15 @@ public:
 
     DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const;
 
+    PipelineCache CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const;
+
     PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const;
 
-    Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci) const;
+    Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci,
+                                    VkPipelineCache cache = nullptr) const;
 
-    Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci) const;
+    Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci,
+                                   VkPipelineCache cache = nullptr) const;
 
     Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;
 
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index e9425b5bdb..fbfa3ba355 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -709,6 +709,7 @@ void Config::ReadRendererValues() {
     ReadGlobalSetting(Settings::values.use_asynchronous_shaders);
     ReadGlobalSetting(Settings::values.use_fast_gpu_time);
     ReadGlobalSetting(Settings::values.use_pessimistic_flushes);
+    ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
     ReadGlobalSetting(Settings::values.bg_red);
     ReadGlobalSetting(Settings::values.bg_green);
     ReadGlobalSetting(Settings::values.bg_blue);
@@ -1348,6 +1349,7 @@ void Config::SaveRendererValues() {
     WriteGlobalSetting(Settings::values.use_asynchronous_shaders);
     WriteGlobalSetting(Settings::values.use_fast_gpu_time);
     WriteGlobalSetting(Settings::values.use_pessimistic_flushes);
+    WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
     WriteGlobalSetting(Settings::values.bg_red);
     WriteGlobalSetting(Settings::values.bg_green);
     WriteGlobalSetting(Settings::values.bg_blue);
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 01f074699c..a3fbe2ad0a 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -29,6 +29,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
     ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
     ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
     ui->use_pessimistic_flushes->setChecked(Settings::values.use_pessimistic_flushes.GetValue());
+    ui->use_vulkan_driver_pipeline_cache->setChecked(
+        Settings::values.use_vulkan_driver_pipeline_cache.GetValue());
 
     if (Settings::IsConfiguringGlobal()) {
         ui->gpu_accuracy->setCurrentIndex(
@@ -58,6 +60,9 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
                                              ui->use_fast_gpu_time, use_fast_gpu_time);
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_pessimistic_flushes,
                                              ui->use_pessimistic_flushes, use_pessimistic_flushes);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache,
+                                             ui->use_vulkan_driver_pipeline_cache,
+                                             use_vulkan_driver_pipeline_cache);
 }
 
 void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
@@ -82,6 +87,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
         ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
         ui->use_pessimistic_flushes->setEnabled(
             Settings::values.use_pessimistic_flushes.UsingGlobal());
+        ui->use_vulkan_driver_pipeline_cache->setEnabled(
+            Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal());
         ui->anisotropic_filtering_combobox->setEnabled(
             Settings::values.max_anisotropy.UsingGlobal());
 
@@ -97,6 +104,9 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
     ConfigurationShared::SetColoredTristate(ui->use_pessimistic_flushes,
                                             Settings::values.use_pessimistic_flushes,
                                             use_pessimistic_flushes);
+    ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache,
+                                            Settings::values.use_vulkan_driver_pipeline_cache,
+                                            use_vulkan_driver_pipeline_cache);
     ConfigurationShared::SetColoredComboBox(
         ui->gpu_accuracy, ui->label_gpu_accuracy,
         static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index 12e816905a..891efc068f 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -40,6 +40,7 @@ private:
     ConfigurationShared::CheckState use_asynchronous_shaders;
     ConfigurationShared::CheckState use_fast_gpu_time;
     ConfigurationShared::CheckState use_pessimistic_flushes;
+    ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache;
 
     const Core::System& system;
 };
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 87a1214710..ccbdcf08f7 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -109,6 +109,16 @@
           </property>
          </widget>
         </item>
+        <item>
+         <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache">
+          <property name="toolTip">
+            <string>Enables GPU vendor-specific pipeline cache. This option can improve shader loading time significantly in cases where the Vulkan driver does not store pipeline cache files internally.</string>
+          </property>
+          <property name="text">
+           <string>Use Vulkan pipeline cache</string>
+          </property>
+         </widget>
+        </item>
         <item>
          <widget class="QWidget" name="af_layout" native="true">
           <layout class="QHBoxLayout" name="horizontalLayout_1">
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 524650144f..c55f81c2f1 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2229,8 +2229,10 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ
     }
 
     switch (target) {
-    case GameListRemoveTarget::GlShaderCache:
     case GameListRemoveTarget::VkShaderCache:
+        RemoveVulkanDriverPipelineCache(program_id);
+        [[fallthrough]];
+    case GameListRemoveTarget::GlShaderCache:
         RemoveTransferableShaderCache(program_id, target);
         break;
     case GameListRemoveTarget::AllShaderCache:
@@ -2271,6 +2273,22 @@ void GMainWindow::RemoveTransferableShaderCache(u64 program_id, GameListRemoveTa
     }
 }
 
+void GMainWindow::RemoveVulkanDriverPipelineCache(u64 program_id) {
+    static constexpr std::string_view target_file_name = "vulkan_pipelines.bin";
+
+    const auto shader_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir);
+    const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
+    const auto target_file = shader_cache_folder_path / target_file_name;
+
+    if (!Common::FS::Exists(target_file)) {
+        return;
+    }
+    if (!Common::FS::RemoveFile(target_file)) {
+        QMessageBox::warning(this, tr("Error Removing Vulkan Driver Pipeline Cache"),
+                             tr("Failed to remove the driver pipeline cache."));
+    }
+}
+
 void GMainWindow::RemoveAllTransferableShaderCaches(u64 program_id) {
     const auto shader_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir);
     const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index db318485df..f25ce65a89 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -347,6 +347,7 @@ private:
     void RemoveUpdateContent(u64 program_id, InstalledEntryType type);
     void RemoveAddOnContent(u64 program_id, InstalledEntryType type);
     void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target);
+    void RemoveVulkanDriverPipelineCache(u64 program_id);
     void RemoveAllTransferableShaderCaches(u64 program_id);
     void RemoveCustomConfiguration(u64 program_id, const std::string& game_path);
     std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 1e45e57bcf..b2d690bb6c 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -321,6 +321,7 @@ void Config::ReadValues() {
     ReadSetting("Renderer", Settings::values.accelerate_astc);
     ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
     ReadSetting("Renderer", Settings::values.use_pessimistic_flushes);
+    ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
 
     ReadSetting("Renderer", Settings::values.bg_red);
     ReadSetting("Renderer", Settings::values.bg_green);