diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 8d32825e419d62464095fb6e4ad0b4a9c809b5ba..a9e1454fed1bad3a61c9158dc21ab368aa4b6182 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -1526,6 +1526,7 @@ static bool d3d12_command_list_update_current_pipeline(struct d3d12_command_list
     struct VkPipelineVertexInputStateCreateInfo input_desc;
     struct VkPipelineColorBlendStateCreateInfo blend_desc;
     struct VkGraphicsPipelineCreateInfo pipeline_desc;
+    const struct d3d12_device *device = list->device;
     struct d3d12_graphics_pipeline_state *state;
     size_t binding_count = 0;
     VkPipeline vk_pipeline;
@@ -1632,7 +1633,7 @@ static bool d3d12_command_list_update_current_pipeline(struct d3d12_command_list
     pipeline_desc.subpass = 0;
     pipeline_desc.basePipelineHandle = VK_NULL_HANDLE;
     pipeline_desc.basePipelineIndex = -1;
-    if ((vr = VK_CALL(vkCreateGraphicsPipelines(list->device->vk_device, VK_NULL_HANDLE,
+    if ((vr = VK_CALL(vkCreateGraphicsPipelines(device->vk_device, device->vk_pipeline_cache,
             1, &pipeline_desc, NULL, &vk_pipeline))) < 0)
     {
         WARN("Failed to create Vulkan graphics pipeline, vr %d.\n", vr);
@@ -1642,7 +1643,7 @@ static bool d3d12_command_list_update_current_pipeline(struct d3d12_command_list
     if (!d3d12_command_allocator_add_pipeline(list->allocator, vk_pipeline))
     {
         WARN("Failed to add pipeline.\n");
-        VK_CALL(vkDestroyPipeline(list->device->vk_device, vk_pipeline, NULL));
+        VK_CALL(vkDestroyPipeline(device->vk_device, vk_pipeline, NULL));
         return false;
     }
 
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 81336ffb0c103fc1803891254e1c47872898564d..b49f479fa930dcdd596aa87a1b33ad4683f3dac5 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -770,6 +770,25 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device)
     return S_OK;
 }
 
+static void d3d12_device_init_pipeline_cache(struct d3d12_device *device)
+{
+    const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+    VkPipelineCacheCreateInfo cache_info;
+    VkResult vr;
+
+    cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+    cache_info.pNext = NULL;
+    cache_info.flags = 0;
+    cache_info.initialDataSize = 0;
+    cache_info.pInitialData = NULL;
+    if ((vr = VK_CALL(vkCreatePipelineCache(device->vk_device, &cache_info, NULL,
+            &device->vk_pipeline_cache))) < 0)
+    {
+        ERR("Failed to create pipeline cache, vr %d.\n", vr);
+        device->vk_pipeline_cache = VK_NULL_HANDLE;
+    }
+}
+
 D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator,
         size_t size, void *ptr)
 {
@@ -888,6 +907,8 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
 
         vkd3d_gpu_va_allocator_cleanup(&device->gpu_va_allocator);
         vkd3d_fence_worker_stop(&device->fence_worker);
+        if (device->vk_pipeline_cache)
+            VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL));
         VK_CALL(vkDestroyDevice(device->vk_device, NULL));
         vkd3d_instance_destroy(&device->vkd3d_instance);
 
@@ -1742,6 +1763,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
 
     vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
 
+    d3d12_device_init_pipeline_cache(device);
+
     return S_OK;
 }
 
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index ca39503b8458d50282741a207f314ee69aa1a68a..d31bd8b5d701034d5a02b917c28a39cc996594c3 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -587,6 +587,8 @@ struct d3d12_device
     struct vkd3d_gpu_va_allocator gpu_va_allocator;
     struct vkd3d_fence_worker fence_worker;
 
+    VkPipelineCache vk_pipeline_cache;
+
     unsigned int direct_queue_family_index;
     unsigned int copy_queue_family_index;
     unsigned int compute_queue_family_index;