diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp
index 49456fec9..0da96f975 100644
--- a/src/d3d11/d3d11_texture.cpp
+++ b/src/d3d11/d3d11_texture.cpp
@@ -23,6 +23,39 @@ namespace dxvk {
   }
   
   
+  /**
+   * \brief Optimizes image layout based on usage flags
+   * 
+   * \param [in] flags Image usage flag
+   * \returns Optimized image layout
+   */
+  static VkImageLayout OptimizeLayout(VkImageUsageFlags flags) {
+    // Filter out unnecessary flags. Transfer operations
+    // are handled by the backend in a transparent manner.
+    flags &= ~(VK_IMAGE_USAGE_TRANSFER_DST_BIT
+             | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+    
+    // If the image is used only as an attachment, we never
+    // have to transform the image back to a different layout
+    if (flags == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
+      return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+    
+    if (flags == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
+      return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+    
+    flags &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
+             | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
+    
+    // If the image is used for reading but not as a storage
+    // image, we can optimize the image for texture access
+    if (flags == VK_IMAGE_USAGE_SAMPLED_BIT)
+      return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+    
+    // Otherwise, we have to stick with the default layout
+    return VK_IMAGE_LAYOUT_GENERAL;
+  }
+  
+  
   /**
    * \brief Fills in image info stage and access flags
    * 
@@ -83,6 +116,9 @@ namespace dxvk {
     
     if (pImageInfo->mipLevels == 0)
       pImageInfo->mipLevels = util::computeMipLevelCount(pImageInfo->extent);
+    
+    if (pImageInfo->tiling == VK_IMAGE_TILING_OPTIMAL)
+      pImageInfo->layout = OptimizeLayout(pImageInfo->usage);
   }