diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp
index 04972b0c0..560872792 100644
--- a/src/dxvk/dxvk_compute.cpp
+++ b/src/dxvk/dxvk_compute.cpp
@@ -24,7 +24,8 @@ namespace dxvk {
     m_library       (library),
     m_libraryHandle (VK_NULL_HANDLE),
     m_shaders       (std::move(shaders)),
-    m_bindings      (layout) {
+    m_bindings      (layout),
+    m_debugName     (createDebugName()) {
 
   }
   
@@ -157,4 +158,12 @@ namespace dxvk {
     Logger::log(level, sstr.str());
   }
 
+
+  std::string DxvkComputePipeline::createDebugName() const {
+    std::string shaderName = m_shaders.cs->debugName();
+    size_t len = std::min(shaderName.size(), size_t(10));
+
+    return str::format("[", shaderName.substr(0, len), "]");
+  }
+
 }
diff --git a/src/dxvk/dxvk_compute.h b/src/dxvk/dxvk_compute.h
index c684d9762..c437d7ad5 100644
--- a/src/dxvk/dxvk_compute.h
+++ b/src/dxvk/dxvk_compute.h
@@ -119,7 +119,17 @@ namespace dxvk {
      */
     void compilePipeline(
       const DxvkComputePipelineStateInfo& state);
-    
+
+    /**
+     * \brief Debug name
+     *
+     * Consists of the compute shader's debug name.
+     * \returns Debug name
+     */
+    const char* debugName() const {
+      return m_debugName.c_str();
+    }
+
   private:
     
     DxvkDevice*                 m_device;    
@@ -132,6 +142,8 @@ namespace dxvk {
     DxvkComputePipelineShaders  m_shaders;
     DxvkBindingLayoutObjects*   m_bindings;
     
+    std::string                 m_debugName;
+
     alignas(CACHE_LINE_SIZE)
     dxvk::mutex                             m_mutex;
     sync::List<DxvkComputePipelineInstance> m_pipelines;
@@ -152,6 +164,8 @@ namespace dxvk {
             LogLevel                      level,
       const DxvkComputePipelineStateInfo& state) const;
 
+    std::string createDebugName() const;
+
   };
   
 }
\ No newline at end of file
diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp
index 320c042c5..960b2b186 100644
--- a/src/dxvk/dxvk_context.cpp
+++ b/src/dxvk/dxvk_context.cpp
@@ -4940,6 +4940,11 @@ namespace dxvk {
     if (newPipeline->getBindings()->layout().getPushConstantRange(true).size)
       m_flags.set(DxvkContextFlag::DirtyPushConstants);
 
+    if (unlikely(m_features.test(DxvkContextFeature::DebugUtils))) {
+      m_cmd->cmdInsertDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer,
+        vk::makeLabel(0xf0dca2, newPipeline->debugName()));
+    }
+
     m_flags.clr(DxvkContextFlag::CpDirtyPipelineState);
     return true;
   }
@@ -5108,6 +5113,11 @@ namespace dxvk {
         dstBarrier.stages, dstBarrier.access);
     }
 
+    if (unlikely(m_features.test(DxvkContextFeature::DebugUtils))) {
+      m_cmd->cmdInsertDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer,
+        vk::makeLabel(0xa2dcf0, m_state.gp.pipeline->debugName()));
+    }
+
     m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
     return true;
   }
diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp
index 1f44f57d5..ec6b2147b 100644
--- a/src/dxvk/dxvk_graphics.cpp
+++ b/src/dxvk/dxvk_graphics.cpp
@@ -945,7 +945,8 @@ namespace dxvk {
     m_bindings      (layout),
     m_barrier       (layout->getGlobalBarrier()),
     m_vsLibrary     (vsLibrary),
-    m_fsLibrary     (fsLibrary) {
+    m_fsLibrary     (fsLibrary),
+    m_debugName     (createDebugName()) {
     m_vsIn  = m_shaders.vs != nullptr ? m_shaders.vs->info().inputMask  : 0;
     m_fsOut = m_shaders.fs != nullptr ? m_shaders.fs->info().outputMask : 0;
     m_specConstantMask = this->computeSpecConstantMask();
@@ -1673,5 +1674,28 @@ namespace dxvk {
 
     Logger::log(level, sstr.str());
   }
+
+
+  std::string DxvkGraphicsPipeline::createDebugName() const {
+    std::stringstream name;
+
+    std::array<Rc<DxvkShader>, 5> shaders = {{
+      m_shaders.vs,
+      m_shaders.tcs,
+      m_shaders.tes,
+      m_shaders.gs,
+      m_shaders.fs,
+    }};
+
+    for (const auto& shader : shaders) {
+      if (shader) {
+        std::string shaderName = shader->debugName();
+        size_t len = std::min(shaderName.size(), size_t(10));
+        name << "[" << shaderName.substr(0, len) << "] ";
+      }
+    }
+
+    return name.str();
+  }
   
 }
diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h
index 5b8ee6b14..3503fd896 100644
--- a/src/dxvk/dxvk_graphics.h
+++ b/src/dxvk/dxvk_graphics.h
@@ -561,6 +561,17 @@ namespace dxvk {
      */
     void releasePipeline();
 
+    /**
+     * \brief Queries debug name for the pipeline
+     *
+     * The pipeline debug name contains the debug name of
+     * each shader included in the pipeline.
+     * \returns Pipeline debug name
+     */
+    const char* debugName() const {
+      return m_debugName.c_str();
+    }
+
   private:
 
     DxvkDevice*                 m_device;    
@@ -582,6 +593,8 @@ namespace dxvk {
 
     uint32_t m_specConstantMask = 0;
 
+    std::string m_debugName;
+
     alignas(CACHE_LINE_SIZE)
     dxvk::mutex                                   m_mutex;
     sync::List<DxvkGraphicsPipelineInstance>      m_pipelines;
@@ -596,7 +609,7 @@ namespace dxvk {
     std::unordered_map<
       DxvkGraphicsPipelineFastInstanceKey,
       VkPipeline, DxvkHash, DxvkEq>               m_fastPipelines;
-    
+
     DxvkGraphicsPipelineInstance* createInstance(
       const DxvkGraphicsPipelineStateInfo& state,
             bool                           doCreateBasePipeline);
@@ -643,6 +656,8 @@ namespace dxvk {
             LogLevel                       level,
       const DxvkGraphicsPipelineStateInfo& state) const;
 
+    std::string createDebugName() const;
+
   };
   
 }
\ No newline at end of file